forked from I2P_Developers/i2p.i2p
Compare commits
451 Commits
Author | SHA1 | Date | |
---|---|---|---|
0ddef91e16 | |||
b205af5a0d | |||
f446a5f1fc | |||
1cd54dc12e | |||
8ebc8bd209 | |||
9d11866f86 | |||
23d3c33a12 | |||
ec8130f443 | |||
4b7aeb8418 | |||
18a0f01f8b | |||
df2e639692 | |||
708b3a662c | |||
4fee7844f8 | |||
891416e6b9 | |||
978cd2c484 | |||
c88c905926 | |||
f5c1acc749 | |||
c4e6148b9f | |||
43029de2f3 | |||
454b2c8941 | |||
4c812c7bff | |||
f95b5324e0 | |||
64ee1b313b | |||
1ca651e803 | |||
f3a88398f2 | |||
278b917494 | |||
0642fa8093 | |||
6371f66677 | |||
105524d9c0 | |||
95e0492b32 | |||
234c084c2a | |||
94faf74aa4 | |||
e78dd1fdc3 | |||
38045d876d | |||
8433724452 | |||
e9f9e0dabb | |||
6bdf750c19 | |||
647a09b5b9 | |||
6144bfb437 | |||
88dbd7710a | |||
26a71232f0 | |||
f58a1768b9 | |||
125e6581e0 | |||
54105086ad | |||
3674ac2922 | |||
18c023e6f7 | |||
312ba2599f | |||
746dc6f884 | |||
edd4d4c114 | |||
56e0c3e047 | |||
1e83d1b304 | |||
74aa84b183 | |||
168c213288 | |||
d268a3852c | |||
01e87438c3 | |||
060f4e6632 | |||
3df5540a97 | |||
30dec5b9f5 | |||
43b437fc58 | |||
8e889cd292 | |||
eceac6def0 | |||
1e3d6776aa | |||
784ca67ddf | |||
0f6b49cc31 | |||
8cede2a2b2 | |||
38ed04bbd8 | |||
c393e70ca9 | |||
1c25c0f408 | |||
b7ebce48ee | |||
d6814a0489 | |||
6f24c74f8c | |||
d8389dcc46 | |||
9f939553ee | |||
529988f394 | |||
9f46aa1e18 | |||
418c1b6f96 | |||
8056fb9502 | |||
ab2e21147f | |||
6c00bb20b6 | |||
573ac357d8 | |||
5b139f9246 | |||
76d75b712e | |||
8bc2fd7e42 | |||
4533a86712 | |||
a6239e2ce3 | |||
1f8e61f480 | |||
c40f845279 | |||
aa74962263 | |||
42cbd6c12b | |||
ee51f69a5a | |||
0fb6e9cf6c | |||
e02845076d | |||
2dc3798116 | |||
fa252f5e8f | |||
580b9b450f | |||
f0730cd1c8 | |||
b045fb3a45 | |||
6c64111d7e | |||
37a2ccca95 | |||
b4615edfcc | |||
6019cf8148 | |||
e3d945201b | |||
05b17e5a00 | |||
13b3edfb07 | |||
f61372b2fd | |||
f85d8f7060 | |||
a0b4b7db86 | |||
827a92ef2f | |||
625d76b914 | |||
a1de894b64 | |||
413ab6d7e4 | |||
a3b1c79006 | |||
5a7d3ba4c8 | |||
8a1db31184 | |||
5190b2db1f | |||
820c573476 | |||
ab40454bce | |||
b65865b854 | |||
a5772e62c3 | |||
9976bea03f | |||
7997aeaca5 | |||
ba95084d27 | |||
e952e91b54 | |||
da21c0ddb7 | |||
0133711c3b | |||
6eae2cd460 | |||
9314eebc4f | |||
428cbdce2a | |||
7594c4383b | |||
e2f6911e9f | |||
9cdae03069 | |||
06946f026e | |||
d43dac5c04 | |||
b4d83b18fa | |||
f9424dbd6d | |||
e5212937af | |||
aeb6635e71 | |||
e94b478317 | |||
88216de42c | |||
1fcf707bb2 | |||
5101486fe7 | |||
7ae4d0e981 | |||
c644c128c0 | |||
2603f6fe45 | |||
957a296ca9 | |||
e4f44fa1e9 | |||
2b469567bb | |||
a2d90eebea | |||
850a8da0a9 | |||
ac6d711a99 | |||
5aa254a178 | |||
ad396adf39 | |||
05cce164f7 | |||
935b69bc71 | |||
61f800999a | |||
9833743eb9 | |||
ac65bc7302 | |||
b36f207bb2 | |||
e87a7c7bb4 | |||
7e5128bb85 | |||
0a178ec35e | |||
a5cd0bdd3f | |||
9cbf9d0422 | |||
097a05aab9 | |||
0e5b2598fb | |||
4f492e33e6 | |||
1828b2bd17 | |||
0c74e640df | |||
ffd2721627 | |||
f6ce4cb29f | |||
4863ef3360 | |||
9f7807ee10 | |||
b2285b0beb | |||
8e4f4f82a8 | |||
db2158d4c1 | |||
1c461bbeda | |||
0757f4f309 | |||
a2f287cdfe | |||
1ef448d518 | |||
f44b1a35bc | |||
26f02a4771 | |||
dc3c730937 | |||
77d45e7a3a | |||
45a59f009b | |||
dc6d6ead69 | |||
27693826a2 | |||
8a647b42d5 | |||
eba9f3c03b | |||
eacf46b367 | |||
83cacaad05 | |||
cf10451d14 | |||
44069645df | |||
4497463778 | |||
10b84418c3 | |||
fadda4ceec | |||
011a32f741 | |||
10bb3c100e | |||
2738d5851d | |||
219095404a | |||
001c361338 | |||
e21a172e95 | |||
4651b7007b | |||
5b4be5ba1b | |||
9c2c90c0b1 | |||
bdd0c3f961 | |||
b7013361c2 | |||
f73b3e522b | |||
fa6d17a1b8 | |||
c3e646ca22 | |||
fdc9e11fb4 | |||
a1ec838282 | |||
7da46517ae | |||
d8e2939307 | |||
8cad72c654 | |||
2cfc2bb60d | |||
1811e3b9cd | |||
960cd18d0a | |||
405b85c4b4 | |||
92e323df51 | |||
3f2c34903d | |||
3c260aa333 | |||
da41f3a93b | |||
aeb711acde | |||
a46ee9a5b2 | |||
088f9558ec | |||
376d61c155 | |||
285a2b92e5 | |||
8939c573ea | |||
3839d9873a | |||
116762ebce | |||
7dd8f00e95 | |||
29a3db4b5c | |||
5d95907996 | |||
2f940d01b6 | |||
517e170b88 | |||
b27fbb9b8e | |||
9b97d32ea8 | |||
d4f3952a90 | |||
f7840652ed | |||
08634c1ff6 | |||
dec4205890 | |||
b49ab59e3b | |||
7e1171ec9f | |||
3eae787957 | |||
9ecba4fc5e | |||
4fb9eef198 | |||
49ecfd8224 | |||
09a2854b8b | |||
82976e609f | |||
b2d6b60300 | |||
90737493e6 | |||
fe3abc79d6 | |||
9931112387 | |||
1cd646afe2 | |||
0d262d28b7 | |||
f33e950780 | |||
7094489536 | |||
2dd650df01 | |||
7e8037979f | |||
3a1c042cd2 | |||
ca81c35b3d | |||
6a2dfff34d | |||
5eccc01de6 | |||
1850e893e9 | |||
2341793546 | |||
1f1d089fda | |||
5372a50bcc | |||
83588d9b98 | |||
58e960ceb5 | |||
de07705671 | |||
49ff3cfbf3 | |||
e392469835 | |||
7745bd89a9 | |||
01bed932c7 | |||
157190757b | |||
e0f1047d72 | |||
15f0cda41f | |||
9a95122c7c | |||
d868f7c02a | |||
5ca2f306b8 | |||
c714c1a0c9 | |||
e6e6c00497 | |||
62a3da2fa6 | |||
f1f97e8ec5 | |||
6c361679c6 | |||
ae89d2f2ab | |||
8053fb5eae | |||
ebf5eb6e20 | |||
2e2bff3f0a | |||
a3f290e4d8 | |||
e0dd1f13e3 | |||
787def6a1c | |||
1f5d7d7b5b | |||
4bc5215833 | |||
7736545f5b | |||
1ecf4377c6 | |||
593d4dc508 | |||
93d366fea1 | |||
7973f2e8b9 | |||
bb14fa0b4e | |||
95aba0c537 | |||
df4143f036 | |||
ed0575e937 | |||
456ed0aab4 | |||
47c8389419 | |||
51fd4d70da | |||
79e32231fb | |||
80f9f857e5 | |||
5a4c2de425 | |||
7e547743c7 | |||
3f3d43df41 | |||
0cc72a49c8 | |||
35c9e99914 | |||
2e4bd1e440 | |||
22c0b8e524 | |||
faeb58f7e2 | |||
cdc184c5e5 | |||
2f9a4f0fa5 | |||
37437da34d | |||
6d3a5856b4 | |||
4d4538a346 | |||
327102a254 | |||
3602eb14f5 | |||
cf82b51a1f | |||
412d3bc2f8 | |||
4735508a0a | |||
9225d01b29 | |||
7782970d51 | |||
6f053287d5 | |||
7a88f59f08 | |||
d56aae8913 | |||
a309a14396 | |||
b80cbbdd4a | |||
5bc2dab1d2 | |||
8bbe7fabb3 | |||
c537d160a6 | |||
475187fcbc | |||
a379e36e24 | |||
a9054a3cab | |||
ea7a9c259f | |||
2cba48d4d7 | |||
42b79c5a20 | |||
be9523f1e4 | |||
6a8dd0f053 | |||
1b63aa411b | |||
33a7f3351b | |||
f7af5e1329 | |||
3a9a029d70 | |||
0aaacc86e2 | |||
1b8b7b741c | |||
66831c619b | |||
30628fb5f9 | |||
064ff8a7d2 | |||
9a18955de3 | |||
35da3f3334 | |||
335d45f03e | |||
c466cd77ad | |||
d998e2e9bb | |||
0a20315280 | |||
01753f5aea | |||
bcd22cfbf3 | |||
7e039d0339 | |||
ab08ac70aa | |||
5decf3cd7a | |||
5c6d757e35 | |||
4b75be804f | |||
6515e6ee17 | |||
55e8583663 | |||
3fbff71861 | |||
e5eea47b66 | |||
b10b0e8f57 | |||
631a367b1c | |||
8ea279fbe2 | |||
089572befd | |||
0f96b9569a | |||
d1114666de | |||
f676abc0d4 | |||
3492b7219b | |||
a12ae6e399 | |||
9b2e18a65b | |||
c52ccf7eef | |||
1282434684 | |||
4e844187f7 | |||
ccd67d658d | |||
62383819cb | |||
3febcf6043 | |||
a431137f45 | |||
5a6e14b9df | |||
536bc3112f | |||
81b2e6b789 | |||
4cf376ec1d | |||
d3a0c91398 | |||
43140d3efd | |||
3dd3bf829d | |||
bdcad06ece | |||
69fdfb0635 | |||
55a8002b9c | |||
e36f9b2273 | |||
70ae99f31a | |||
15565ca09c | |||
f188e02a5d | |||
4d005349a7 | |||
c65a97882e | |||
cf880548d9 | |||
b5876e7f04 | |||
2436ea1131 | |||
5395b6829a | |||
c3af134a5b | |||
cce72a5f1b | |||
32c143f8d7 | |||
895cb1f2e5 | |||
7986f5646e | |||
59a5776f9d | |||
fc8c0ccfe1 | |||
0930ead814 | |||
b5a17637cb | |||
460c8a319f | |||
7aa051ef4f | |||
c7c132c0ac | |||
d84b1125eb | |||
8d4a1899f2 | |||
3a0cdf1388 | |||
d8d76fd327 | |||
abf7296de1 | |||
316c20ee44 | |||
13e8c95667 | |||
a14ad423a6 | |||
e1a5d5e19a | |||
6e29eddaa7 | |||
65ae26a961 | |||
1afd946a94 | |||
d6820634ac | |||
95dd744633 | |||
219af36090 | |||
24e83398ba | |||
4172ed21a9 | |||
1cba7b8ec1 | |||
0bef85277e | |||
2f4c428316 | |||
4de0b73cd8 | |||
2e5caac8bf | |||
7972c0c862 | |||
3fee5a3781 | |||
db45e74fcc | |||
206e45b9e8 | |||
5022575429 | |||
b8f22bf3bf | |||
5a8b3eb8f3 | |||
d26ac84126 | |||
82045b3fde | |||
14ce5a2432 |
@ -3,9 +3,10 @@ Headless I2P installation instructions
|
||||
1) java -jar i2pinstall.exe -console (you've already done this)
|
||||
|
||||
This will run the installer in text mode, including running the postinstall.sh
|
||||
script, which will start the router and launch a browser.
|
||||
script. After that, you may run 'sh i2prouter start'
|
||||
which will start the router and attempt to launch a browser.
|
||||
|
||||
If you do not have an X server running, the browser launch will fail, and
|
||||
If you do not have an X server running, the browser launch will probably fail, and
|
||||
you may use:
|
||||
lynx http://localhost:7657/index.jsp
|
||||
to configure the router.
|
||||
@ -13,6 +14,16 @@ to configure the router.
|
||||
If you're having trouble, swing by http://forum.i2p2.de/, check the
|
||||
website at http://www.i2p2.de/, or get on irc://irc.freenode.net/#i2p
|
||||
|
||||
I2P will create and store files and configuration data in the user directory
|
||||
~/.i2p/ on Linux and %APPDATA%\I2P\ on Windows. This directory is created
|
||||
when I2P is run for the first time. It also creates files in the system
|
||||
temporary directory specified by the Java Virtual Machine.
|
||||
To change the location of these directories, or to configure I2P to
|
||||
put all files in this directory (the so-called "portable" configuration),
|
||||
edit the files i2prouter (Linux) and wrapper.config (Linux and Windows)
|
||||
where there are comments labeled "PORTABLE". Do this before you
|
||||
run I2P for the first time.
|
||||
|
||||
To run I2P explicitly:
|
||||
(*nix): sh i2prouter start
|
||||
(win*): I2P.exe
|
||||
|
@ -76,9 +76,6 @@ Public domain except as listed below:
|
||||
Copyright (C) 2003-2006 Satoshi Konno
|
||||
See licenses/LICENSE-UPnP.txt
|
||||
|
||||
XMLPull library used by UPnP:
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
|
||||
GeoIP data free to use, courtesy http://ip-to-country.webhosting.info/
|
||||
|
||||
|
||||
|
51
Makefile.gcj
51
Makefile.gcj
@ -5,7 +5,7 @@
|
||||
GCJ=gcj #/usr/local/gcc-4.0.2/bin/gcj
|
||||
EXTRA_LD_PATH= #/usr/local/gcc-4.0.2/lib
|
||||
ANT=ant #/opt/apache-ant-1.6.5/bin/ant
|
||||
ANT_TARGET=buildclean
|
||||
ANT_TARGET=build2
|
||||
NATIVE_DIR=native
|
||||
|
||||
##
|
||||
@ -24,20 +24,22 @@ JAR_BASE=i2p.jar mstreaming.jar streaming.jar
|
||||
JAR_CLIENTS=i2ptunnel.jar sam.jar
|
||||
JAR_ROUTER=router.jar
|
||||
JAR_JBIGI=jbigi.jar
|
||||
JAR_XML=xml-apis.jar resolver.jar xercesImpl.jar
|
||||
JAR_CONSOLE=\
|
||||
i2psnark.jar \
|
||||
javax.servlet.jar \
|
||||
commons-el.jar \
|
||||
commons-logging.jar \
|
||||
jasper-runtime.jar \
|
||||
ant-apache-bcel.jar \
|
||||
ant.jar \
|
||||
jasper-compiler.jar \
|
||||
org.mortbay.jetty.jar \
|
||||
routerconsole.jar
|
||||
JAR_SUCKER=jdom.jar rome-0.7.jar sucker.jar
|
||||
LIBI2P_JARS=${JAR_BASE} ${JAR_CLIENTS} ${JAR_ROUTER} ${JAR_JBIGI}
|
||||
LIBSAM_JARS=${JAR_BASE} sam.jar
|
||||
LIBROUTER_JARS=i2p.jar ${JAR_ROUTER} ${JAR_JBIGI}
|
||||
LIBCONSOLE_JARS=${LIBROUTER_JARS} ${JAR_CONSOLE}
|
||||
LIBSNARK_JARS=${LIBROUTER_JARS} i2psnark.jar
|
||||
# update:
|
||||
# similar error with gcj 4.3.3.
|
||||
#
|
||||
# unfortunately, its not quite ready for most end users, as the
|
||||
# ${JAR_CONSOLE} fails to compile with:
|
||||
# org/apache/commons/logging/impl/LogKitLogger.java: In class 'org.apache.commons.logging.impl.LogKitLogger':
|
||||
@ -95,7 +97,36 @@ native_shared: libi2p.so
|
||||
@echo " i2ptunnel will, so it will start all the proxies defined in i2ptunnel.config"
|
||||
|
||||
libi2p.so:
|
||||
@echo "* Building libi2p.so"
|
||||
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/libi2p.so ${LIBI2P_JARS} ; cd .. )
|
||||
@ls -l ${NATIVE_DIR}/libi2p.so
|
||||
@echo "* libi2p.so built"
|
||||
@echo "* Building $@"
|
||||
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/$@ ${LIBI2P_JARS} ; cd .. )
|
||||
@ls -l ${NATIVE_DIR}/$@
|
||||
@echo "* $@ built"
|
||||
|
||||
sam: jars libi2psam.so
|
||||
|
||||
libi2psam.so:
|
||||
@echo "* Building $@"
|
||||
@rm -f ${NATIVE_DIR}/$@
|
||||
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/$@ ${LIBSAM_JARS} ; cd .. )
|
||||
@ls -l ${NATIVE_DIR}/$@
|
||||
@echo "* $@ built"
|
||||
|
||||
router: jars libi2prouter.so
|
||||
|
||||
libi2prouter.so:
|
||||
@echo "* Building $@"
|
||||
@rm -f ${NATIVE_DIR}/$@
|
||||
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/$@ ${LIBROUTER_JARS} ; cd .. )
|
||||
@ls -l ${NATIVE_DIR}/$@
|
||||
@echo "* $@ built"
|
||||
|
||||
console: jars libi2pconsole.so
|
||||
|
||||
# doesn't work, see above
|
||||
libi2pconsole.so:
|
||||
@echo "* Building $@"
|
||||
@rm -f ${NATIVE_DIR}/$@
|
||||
@(cd build ; time ${GCJ} ${OPTIMIZE} -fPIC -fjni -shared -o ../${NATIVE_DIR}/$@ ${LIBCONSOLE_JARS} ; cd .. )
|
||||
@ls -l ${NATIVE_DIR}/$@
|
||||
@echo "* $@ built"
|
||||
|
||||
|
@ -1,43 +1,155 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
#
|
||||
# Now in the future we only need to look for '#I2P' and '#/I2P'
|
||||
# for modifications to rc.local and rc.local_shutdown.
|
||||
# I was a moron for not doing it this way in the first place :-) -- Sponge
|
||||
#
|
||||
#
|
||||
|
||||
touch /etc/rc.d/rc.local
|
||||
touch /etc/rc.d/rc.local_shutdown
|
||||
|
||||
I2PRCA=`grep -c /etc/rc.d/rc.local -e i2p`
|
||||
I2PRCB=`grep -c /etc/rc.d/rc.local_shutdown -e i2p`
|
||||
|
||||
echo
|
||||
echo -n "Check 1: /etc/rc.d/rc.local "
|
||||
I2PRCA=`grep -c /etc/rc.d/rc.local -e '/etc/rc.d/rc.i2p'`
|
||||
|
||||
if [ $I2PRCA -eq 0 ] ; then
|
||||
echo '#I2P' >> /etc/rc.d/rc.local
|
||||
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
|
||||
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
|
||||
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
|
||||
echo "fi" >> /etc/rc.d/rc.local
|
||||
echo "/etc/rc.d/rc.local modified."
|
||||
echo '#/I2P' >> /etc/rc.d/rc.local
|
||||
echo "modified."
|
||||
else
|
||||
echo "/etc/rc.d/rc.local looks OK"
|
||||
echo -n "looks OK so far,"
|
||||
# Fix old installs, or where people have modified.
|
||||
|
||||
echo -n " Check 1A: "
|
||||
I2PRCC=`grep -c /etc/rc.d/rc.local -e 'i2p-\*\.tmp'`
|
||||
|
||||
if [ $I2PRCC -eq 0 ] ; then
|
||||
DATA=$(cat /etc/rc.d/rc.local | sed -re 's/if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/#I2P\n\( cd \/tmp ; rm -Rf i2p-*.tmp \)\nif \[ -x \/etc\/rc.d\/rc.i2p \] ; then/')
|
||||
echo "${DATA}" > /etc/rc.d/rc.local
|
||||
echo -n "additional modifications applied,"
|
||||
else
|
||||
echo -n "looks OK so far,"
|
||||
fi
|
||||
|
||||
echo -n " Check 1B: "
|
||||
I2PRCE=`grep -c /etc/rc.d/rc.local -e 'i2p-\*\.tmp'`
|
||||
if [ $I2PRCE -eq 0 ] ; then
|
||||
DATATOP=$(cat /etc/rc.d/rc.local | sed -n '0,/i2p-\*\.tmp/p' | sed '$d' )
|
||||
DATABOT=$(cat /etc/rc.d/rc.local | sed -n '/i2p-\*\.tmp/,$p' | sed -n '/^fi/,$p' | sed "1d")
|
||||
echo "${DATATOP}" > /etc/rc.d/rc.local
|
||||
echo '#I2P' >> /etc/rc.d/rc.local
|
||||
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
|
||||
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
|
||||
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
|
||||
echo "fi" >> /etc/rc.d/rc.local
|
||||
echo '#/I2P' >> /etc/rc.d/rc.local
|
||||
echo "${DATABOT}" >> /etc/rc.d/rc.local
|
||||
|
||||
echo -n "additional modifications applied,"
|
||||
else
|
||||
echo -n "looks ok so far,"
|
||||
fi
|
||||
echo -n " Check 1C: "
|
||||
I2PRCF=`grep -c /etc/rc.d/rc.local -e '#/I2P'`
|
||||
if [ $I2PRCF -eq 0 ] ; then
|
||||
DATATOP=$(cat /etc/rc.d/rc.local | sed -n '0,/^#I2P/p' | sed '$d' )
|
||||
DATABOT=$(cat /etc/rc.d/rc.local | sed -n '/^#I2P/,$p' | sed -n '/^fi/,$p' | sed "1d")
|
||||
echo "${DATATOP}" > /etc/rc.d/rc.local
|
||||
echo '#I2P' >> /etc/rc.d/rc.local
|
||||
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
|
||||
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
|
||||
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
|
||||
echo "fi" >> /etc/rc.d/rc.local
|
||||
echo '#/I2P' >> /etc/rc.d/rc.local
|
||||
echo "${DATABOT}" >> /etc/rc.d/rc.local
|
||||
|
||||
echo -n "additional modifications applied,"
|
||||
else
|
||||
echo -n "looks ok so far,"
|
||||
fi
|
||||
echo " Done."
|
||||
fi
|
||||
|
||||
echo -n "Check 2: /etc/rc.d/rc.local_shutdown "
|
||||
I2PRCB=`grep -c /etc/rc.d/rc.local_shutdown -e '/etc/rc.d/rc.i2p'`
|
||||
if [ $I2PRCB -eq 0 ] ; then
|
||||
echo "#I2P" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
|
||||
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "fi" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "/etc/rc.d/rc.local_shutdown modified."
|
||||
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "modified."
|
||||
else
|
||||
echo "/etc/rc.d/rc.local_shutdown looks OK"
|
||||
echo -n "looks OK so far,"
|
||||
# Fix old installs
|
||||
|
||||
echo -n " Check 1A: "
|
||||
I2PRCG=`grep -c /etc/rc.d/rc.local_shutdown -e '#I2P'`
|
||||
if [ $I2PRCG -eq 0 ] ; then
|
||||
DATATOP=$(cat /etc/rc.d/rc.local_shutdown | sed -n '0,/^if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/p' | sed '$d' )
|
||||
DATABOT=$(cat /etc/rc.d/rc.local_shutdown | sed -n '/^if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/,$p' | sed -n '/^fi/,$p' | sed "1d")
|
||||
echo "${DATATOP}" > /etc/rc.d/rc.local_shutdown
|
||||
echo '#I2P' >> /etc/rc.d/rc.local_shutdown
|
||||
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
|
||||
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "fi" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "${DATABOT}" >> /etc/rc.d/rc.local_shutdown
|
||||
echo -n "additional modifications applied,"
|
||||
else
|
||||
echo -n "looks OK so far,"
|
||||
fi
|
||||
echo -n " Check 1B: "
|
||||
I2PRCH=`grep -c /etc/rc.d/rc.local_shutdown -e '#/I2P'`
|
||||
if [ $I2PRCH -eq 0 ] ; then
|
||||
DATATOP=$(cat /etc/rc.d/rc.local_shutdown | sed -n '0,/^#I2P/p' | sed '$d' )
|
||||
DATABOT=$(cat /etc/rc.d/rc.local_shutdown | sed -n '/^#I2P/,$p' | sed -n '/^fi/,$p' | sed "1d")
|
||||
echo "${DATATOP}" > /etc/rc.d/rc.local_shutdown
|
||||
echo '#I2P' >> /etc/rc.d/rc.local_shutdown
|
||||
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
|
||||
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "fi" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
|
||||
echo "${DATABOT}" >> /etc/rc.d/rc.local_shutdown
|
||||
echo -n "additional modifications applied,"
|
||||
else
|
||||
echo -n "looks OK so far,"
|
||||
fi
|
||||
echo " Done."
|
||||
fi
|
||||
|
||||
if [ -f /etc/rc.d/rc.i2p ] ; then
|
||||
if [ -x /etc/rc.d/rc.i2p ] ; then
|
||||
chmod +x /etc/rc.d/rc.i2p.new
|
||||
fi
|
||||
echo
|
||||
# Hopefully get admin's attention.
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -e "\007" ; sleep 0.3
|
||||
echo "It apears that you already have /etc/rc.d/rc.i2p"
|
||||
echo "You may wish to replace it with /etc/rc.d/rc.i2p.new"
|
||||
echo
|
||||
echo "You should replace it with /etc/rc.d/rc.i2p.new as soon as possible"
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -ne "\007" ; sleep 0.3
|
||||
echo -e "\007" ; sleep 0.3
|
||||
else
|
||||
mv /etc/rc.d/rc.i2p.new /etc/rc.d/rc.i2p
|
||||
echo
|
||||
echo "Installation finished. The i2p start/stop script has been"
|
||||
echo "installed on /etc/rc.d directory. You should chmod +x"
|
||||
echo "installed in /etc/rc.d . You should chmod +x"
|
||||
echo '/etc/rc.d/rc.i2p to start it on boot.'
|
||||
echo
|
||||
fi
|
||||
|
@ -1,42 +1,57 @@
|
||||
#!/bin/sh
|
||||
# Heavily based on the Slackware 12.1 SlackBuild
|
||||
# Slackware build script for i2p
|
||||
|
||||
#
|
||||
# Heavily based on the Slackware 12.2 SlackBuild
|
||||
# Slackware build script for I2P
|
||||
#
|
||||
# PLEASE READ THIS:
|
||||
# Probably you will never have to update i2p packages with upgradepkg,
|
||||
# just because i2p have an auto-update function.
|
||||
# How to start i2p:
|
||||
# After installpkg command, doinst.sh will execute a postinstallation script
|
||||
# needed by i2p. After that you have to chmod +x /etc/rc.d/rc.i2p and start
|
||||
# i2p service with /etc/rc.d/rc.i2p start.
|
||||
# How to start I2P:
|
||||
# After installpkg command, doinst.sh will execute a post-installation script
|
||||
# needed by I2P. After that you have to chmod +x /etc/rc.d/rc.i2p and start
|
||||
# I2P service with /etc/rc.d/rc.i2p start.
|
||||
#
|
||||
# Now tell your browser to user this proxy: localhost on port 4444 and open
|
||||
# this page: http://localhost:7657/index.jsp
|
||||
# Here you can configure i2p, watch network status and navigate anonimously.
|
||||
#
|
||||
# Here you can configure I2P, watch network status and navigate anonimously.
|
||||
# It's suggested to subscribe to various dns host, like i2host.i2p
|
||||
# For any additional information, visit i2host.i2p and forum.i2p
|
||||
#
|
||||
|
||||
CWD=$(pwd)
|
||||
TMP=/tmp
|
||||
PKG=/$TMP/package-base-i2p
|
||||
rm -rf $PKG
|
||||
mkdir -p $PKG
|
||||
# put here installation dir, without first and last /
|
||||
# es: usr/local
|
||||
NAME=i2p-base
|
||||
VERSION=0.0.1
|
||||
BUILD=1sim
|
||||
VERSION=0.0.2
|
||||
BUILD=1sponge
|
||||
ARCH=noarch
|
||||
INSTALL_DIR=opt
|
||||
|
||||
# Less than slackware 13?
|
||||
SLKPLT=$(cat /etc/slackware-version | sed -re "s/(Slackware )([0-9]*)(.*)/\2/")
|
||||
if [ $SLKPLT -lt 13 ] ; then
|
||||
EXT=tgz
|
||||
else
|
||||
EXT=txz
|
||||
fi
|
||||
|
||||
rm -rf $PKG
|
||||
mkdir -p $PKG
|
||||
cd $PKG
|
||||
chown -R root:root .
|
||||
|
||||
mkdir -p $PKG/etc/rc.d
|
||||
mkdir -p $PKG/install
|
||||
sed "s|directory|/$INSTALL_DIR/i2p/i2prouter|g" $CWD/rc.i2p_def > $PKG/etc/rc.d/rc.i2p.new
|
||||
sed "s|directory|/$INSTALL_DIR/i2p/i2prouter|g" "$CWD/rc.i2p_def" > $PKG/etc/rc.d/rc.i2p.new
|
||||
chmod 644 $PKG/etc/rc.d/rc.i2p.new
|
||||
sed "s|directory|/$INSTALL_DIR/i2p/|g" $CWD/doinst.sh > $PKG/install/doinst.sh
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
cat "$CWD/doinst.sh" > $PKG/install/doinst.sh
|
||||
cat "$CWD/slack-desc" > $PKG/install/slack-desc
|
||||
|
||||
cd $PKG
|
||||
requiredbuilder -v -y -s $CWD $PKG
|
||||
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
|
||||
#
|
||||
# Not really that important to exec this
|
||||
# as there aren't any deps we don't know.
|
||||
#
|
||||
# requiredbuilder -v -y -s $CWD $PKG
|
||||
#
|
||||
cat "$CWD/slack-required" > $PKG/install/slack-required
|
||||
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.$EXT
|
||||
|
@ -9,6 +9,22 @@ i2p_stop() {
|
||||
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory stop )"
|
||||
}
|
||||
|
||||
i2p_restart() {
|
||||
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory restart)"
|
||||
}
|
||||
|
||||
i2p_status() {
|
||||
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory status )"
|
||||
}
|
||||
|
||||
i2p_console() {
|
||||
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory console )"
|
||||
}
|
||||
|
||||
i2p_dump() {
|
||||
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory dump )"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'start')
|
||||
i2p_start
|
||||
@ -17,11 +33,19 @@ case "$1" in
|
||||
i2p_stop
|
||||
;;
|
||||
'restart')
|
||||
i2p_stop
|
||||
i2p_start
|
||||
i2p_restart
|
||||
;;
|
||||
'status')
|
||||
i2p_status
|
||||
;;
|
||||
'console')
|
||||
i2p_console
|
||||
;;
|
||||
'dump')
|
||||
i2p_dump
|
||||
;;
|
||||
*)
|
||||
echo "usage $0 start|stop|restart"
|
||||
echo "usage $0 start|stop|restart|status|console|dump"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -1,28 +1,35 @@
|
||||
#!/bin/sh
|
||||
# Heavily based on the Slackware 12.1 SlackBuild
|
||||
# Slackware build script for i2p
|
||||
|
||||
#
|
||||
# Heavily based on the Slackware 12.2 SlackBuild
|
||||
# Slackware build script for I2P
|
||||
#
|
||||
# PLEASE READ THIS:
|
||||
# Probably you will never have to update i2p packages with upgradepkg,
|
||||
# just because i2p have an auto-update function.
|
||||
# How to start i2p:
|
||||
# After installpkg command, doinst.sh will execute a postinstallation script
|
||||
# needed by i2p. After that you have to chmod +x /etc/rc.d/rc.i2p and start
|
||||
# i2p service with /etc/rc.d/rc.i2p start.
|
||||
# Now tell your browser to user this proxy: localhost on port 4444 and open
|
||||
# this page: http://localhost:7657/index.jsp
|
||||
# Here you can configure i2p, watch network status and navigate anonimously.
|
||||
# It's suggested to subscribe to various dns host, like i2host.i2p
|
||||
# For any additional information, visit i2host.i2p and forum.i2p
|
||||
# Probably you will never have to update I2P packages with upgradepkg,
|
||||
# just because I2P has an auto-update function.
|
||||
# Really you should not ever use any "upgrade" method.
|
||||
#
|
||||
# The correct way to upgrade is to:
|
||||
# 1: install the upgrade
|
||||
# 2: remove the old package
|
||||
#
|
||||
# It is a terrible shame that upgradepkg doesn't do this, infact,
|
||||
# it would actually be the correct way for *any* package!
|
||||
#
|
||||
#
|
||||
|
||||
BUILD=1sim
|
||||
|
||||
# put here installation dir, without first and last /
|
||||
# eg: usr/local
|
||||
BUILD=1sponge
|
||||
INSTALL_DIR=opt
|
||||
NAME=i2p
|
||||
ARCH=noarch
|
||||
|
||||
# Less than slackware 13?
|
||||
SLKPLT=$(cat /etc/slackware-version | sed -re "s/(Slackware )([0-9]*)(.*)/\2/")
|
||||
if [ $SLKPLT -lt 13 ] ; then
|
||||
EXT=tgz
|
||||
else
|
||||
EXT=txz
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# This mess is here due to the totally moronic way i2p does versioning.
|
||||
@ -113,5 +120,11 @@ sed "s|directory|/$INSTALL_DIR/i2p/|g" $CWD/doinst.sh > $PKG/install/doinst.sh
|
||||
cat $CWD/slack-desc > $PKG/install/slack-desc
|
||||
|
||||
cd $PKG
|
||||
requiredbuilder -v -y -s $CWD $PKG
|
||||
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
|
||||
#
|
||||
# requiredbuilder fucks up REALLY bad, and thinks java is perl?!
|
||||
# It also did not catch the shell requirements! BOOOOOOOOOOO! HISSSSSSSS!
|
||||
#
|
||||
# requiredbuilder -v -y -s $CWD $PKG
|
||||
#
|
||||
cat $CWD/slack-required > $PKG/install/slack-required
|
||||
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.$EXT
|
||||
|
@ -1,2 +1,4 @@
|
||||
glibc >= 2.7-i486-17 | glibc-solibs >= 2.7-i486-17
|
||||
perl >= 5.10.0-i486-1
|
||||
jre >= 5
|
||||
i2p-base >= 0.0.1
|
||||
bash >= 3.1.017
|
||||
|
||||
|
19
android/AndroidManifest.xml
Normal file
19
android/AndroidManifest.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.i2p.router"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0.0">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- 3 = 1.5, 2 = 1.1, 1 = 1.0; would probably work with 1 but don't have a 1.0 SDK to test against -->
|
||||
<uses-sdk android:minSdkVersion="2" />
|
||||
<application android:label="@string/app_name">
|
||||
<activity android:name=".I2PAndroid"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
29
android/README.txt
Normal file
29
android/README.txt
Normal file
@ -0,0 +1,29 @@
|
||||
These instructions are for the 1.5 Android SDK.
|
||||
The build file is not compatible with the 1.1 SDK any more.
|
||||
1.6 and 2.0 SDKs are untested.
|
||||
|
||||
#Unzip the android SDK in ../../
|
||||
#So then the android tools will be in ../../android-sdk-linux_x86-1.5_r2/tools/
|
||||
|
||||
# create a file local.properties with the following line:
|
||||
# sdk-location=/path/to/your/android-sdk-linux_x86-1.5_r2
|
||||
|
||||
#then build the android apk file:
|
||||
ant debug
|
||||
|
||||
# Create the android 1.5 virtual device
|
||||
# (don't make a custom hardware profile)
|
||||
../../android-sdk-linux_x86-1.5_r2/tools/android create avd --name i2p --target 2
|
||||
|
||||
#then run the emulator:
|
||||
../../android-sdk-linux_x86-1.5_r2/tools/emulator -avd i2p &
|
||||
|
||||
#then wait a couple minutes until the emulator is up
|
||||
#then install the I2P app
|
||||
ant install
|
||||
|
||||
#then run the debugger
|
||||
../../android-sdk-linux_x86-1.5_r2/tools/ddms &
|
||||
|
||||
#to rebuild and reinstall to emulator:
|
||||
ant reinstall
|
352
android/build.xml
Normal file
352
android/build.xml
Normal file
@ -0,0 +1,352 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name=".I2PAndroid" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contain the path to the SDK. It should *NOT* be checked in in Version
|
||||
Control Systems. -->
|
||||
<property file="local.properties"/>
|
||||
|
||||
<!-- The build.properties file can be created by you and is never touched
|
||||
by the 'android' tool. This is the place to change some of the default property values
|
||||
used by the Ant rules.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
application-package
|
||||
the name of your application package as defined in the manifest. Used by the
|
||||
'uninstall' rule.
|
||||
source-folder
|
||||
the name of the source folder. Default is 'src'.
|
||||
out-folder
|
||||
the name of the output folder. Default is 'bin'.
|
||||
|
||||
Properties related to the SDK location or the project target should be updated
|
||||
using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your application and
|
||||
should be checked in in Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="build.properties"/>
|
||||
|
||||
<!-- The default.properties file is created and updated by the 'android' tool, as well
|
||||
as ADT.
|
||||
This file is an integral part of the build system for your application and
|
||||
should be checked in in Version Control Systems. -->
|
||||
<property file="default.properties"/>
|
||||
|
||||
<!-- Custom Android task to deal with the project target, and import the proper rules.
|
||||
This requires ant 1.6.0 or above. -->
|
||||
<path id="android.antlibs">
|
||||
<pathelement path="${sdk-location}/tools/lib/anttasks.jar" />
|
||||
<pathelement path="${sdk-location}/tools/lib/sdklib.jar" />
|
||||
<pathelement path="${sdk-location}/tools/lib/androidprefs.jar" />
|
||||
<pathelement path="${sdk-location}/tools/lib/apkbuilder.jar" />
|
||||
<pathelement path="${sdk-location}/tools/lib/jarutils.jar" />
|
||||
</path>
|
||||
|
||||
<taskdef name="setup"
|
||||
classname="com.android.ant.SetupTask"
|
||||
classpathref="android.antlibs"/>
|
||||
|
||||
<!-- Execute the Android Setup task that will setup some properties specific to the target,
|
||||
and import the rules files.
|
||||
To customize the rules, copy/paste them below the task, and disable import by setting
|
||||
the import attribute to false:
|
||||
<setup import="false" />
|
||||
|
||||
This will ensure that the properties are setup correctly but that your customized
|
||||
targets are used.
|
||||
-->
|
||||
<setup import="false" />
|
||||
|
||||
<!--
|
||||
================================================================================
|
||||
New I2P rules
|
||||
================================================================================
|
||||
-->
|
||||
|
||||
<target name="buildrouter" depends="dirs" >
|
||||
<!-- build router and core -->
|
||||
<ant dir=".." target="buildrouter" />
|
||||
|
||||
<!-- router -->
|
||||
<copy file="../build/router.jar" todir="${external-libs-folder}" />
|
||||
|
||||
<!-- core -->
|
||||
<mkdir dir="tmp" />
|
||||
<unjar src="../build/i2p.jar" dest="tmp/" />
|
||||
<delete file="tmp/net/i2p/util/LogWriter.class" />
|
||||
<!-- org.bouncycastle.crypto already in android
|
||||
but we need a little trickery because our HMac is incompatible...
|
||||
and the libs aren't in the SDK to compile against??? -->
|
||||
<jar destfile="${external-libs-folder}/crypto.jar" >
|
||||
<fileset dir="tmp/" >
|
||||
<include name="org/bouncycastle/crypto/Digest.class" />
|
||||
<include name="org/bouncycastle/crypto/Mac.class" />
|
||||
<include name="org/bouncycastle/crypto/digests/GeneralDigest.class" />
|
||||
<include name="org/bouncycastle/crypto/digests/MD5Digest.class" />
|
||||
</fileset>
|
||||
</jar>
|
||||
<delete>
|
||||
<fileset dir="tmp/" >
|
||||
<include name="org/bouncycastle/crypto/Digest.class" />
|
||||
<include name="org/bouncycastle/crypto/Mac.class" />
|
||||
<include name="org/bouncycastle/crypto/digests/GeneralDigest.class" />
|
||||
<include name="org/bouncycastle/crypto/digests/MD5Digest.class" />
|
||||
</fileset>
|
||||
</delete>
|
||||
<!--
|
||||
<delete dir="tmp/org/bouncycastle/" />
|
||||
<delete file="tmp/net/i2p/crypto/HMACGenerator.class" />
|
||||
-->
|
||||
<delete file="tmp/org/bouncycastle/" />
|
||||
<!-- lots of unneeded stuff could be deleted here -->
|
||||
<jar destfile="${external-libs-folder}/i2p.jar" basedir="tmp/" />
|
||||
|
||||
<!-- some resources -->
|
||||
<mkdir dir="res/drawable/" />
|
||||
<copy file="../installer/resources/themes/console/images/i2plogo.png" todir="res/drawable/" />
|
||||
<copy file="../installer/resources/blocklist.txt" tofile="res/raw/blocklist_txt" />
|
||||
</target>
|
||||
|
||||
<target name="hackcleanup">
|
||||
<delete file="${external-libs-folder}/crypto.jar" />
|
||||
</target>
|
||||
|
||||
<!--
|
||||
================================================================================
|
||||
From here down copied from SDK platforms/android-1.1/templates/android_rules.xml
|
||||
and then modified
|
||||
================================================================================
|
||||
-->
|
||||
|
||||
<!--
|
||||
This rules file is meant to be imported by the custom Ant task:
|
||||
com.android.ant.AndroidInitTask
|
||||
|
||||
The following properties are put in place by the importing task:
|
||||
android-jar, android-aidl, aapt, aidl, and dx
|
||||
|
||||
Additionnaly, the task sets up the following classpath reference:
|
||||
android.target.classpath
|
||||
This is used by the compiler task as the boot classpath.
|
||||
-->
|
||||
|
||||
<!-- Custom tasks -->
|
||||
<taskdef name="aaptexec"
|
||||
classname="com.android.ant.AaptExecLoopTask"
|
||||
classpathref="android.antlibs"/>
|
||||
|
||||
<taskdef name="apkbuilder"
|
||||
classname="com.android.ant.ApkBuilderTask"
|
||||
classpathref="android.antlibs"/>
|
||||
|
||||
<!-- Properties -->
|
||||
|
||||
<property name="android-tools" value="${sdk-location}/tools" />
|
||||
|
||||
<!-- Input directories -->
|
||||
<property name="source-folder" value="src" />
|
||||
<property name="gen-folder" value="gen" />
|
||||
<property name="resource-folder" value="res" />
|
||||
<property name="asset-folder" value="assets" />
|
||||
<property name="source-location" value="${basedir}/${source-folder}" />
|
||||
|
||||
<!-- folder for the 3rd party java libraries -->
|
||||
<property name="external-libs-folder" value="libs" />
|
||||
|
||||
<!-- folder for the native libraries -->
|
||||
<property name="native-libs-folder" value="libs" />
|
||||
|
||||
<!-- Output directories -->
|
||||
<property name="gen-folder" value="gen" />
|
||||
<property name="out-folder" value="bin" />
|
||||
<property name="out-classes" value="${out-folder}/classes" />
|
||||
<property name="out-classes-location" value="${basedir}/${out-classes}"/>
|
||||
<!-- out folders for a parent project if this project is an instrumentation project -->
|
||||
<property name="main-out-folder" value="../${out-folder}" />
|
||||
<property name="main-out-classes" value="${main-out-folder}/classes"/>
|
||||
|
||||
<!-- Intermediate files -->
|
||||
<property name="dex-file" value="classes.dex" />
|
||||
<property name="intermediate-dex" value="${out-folder}/${dex-file}" />
|
||||
<!-- dx does not properly support incorrect / or \ based on the platform
|
||||
and Ant cannot convert them because the parameter is not a valid path.
|
||||
Because of this we have to compute different paths depending on the platform. -->
|
||||
<condition property="intermediate-dex-location"
|
||||
value="${basedir}\${intermediate-dex}"
|
||||
else="${basedir}/${intermediate-dex}" >
|
||||
<os family="windows"/>
|
||||
</condition>
|
||||
|
||||
<!-- The final package file to generate -->
|
||||
<property name="out-debug-package" value="${out-folder}/${ant.project.name}-debug.apk"/>
|
||||
|
||||
<!-- Tools -->
|
||||
<condition property="exe" value=".exe" else=""><os family="windows"/></condition>
|
||||
<property name="adb" value="${android-tools}/adb${exe}"/>
|
||||
|
||||
<!-- rules -->
|
||||
|
||||
<!-- Create the output directories if they don't exist yet. -->
|
||||
<target name="dirs">
|
||||
<echo>Creating output directories if needed...</echo>
|
||||
<mkdir dir="${resource-folder}" />
|
||||
<mkdir dir="${external-libs-folder}" />
|
||||
<mkdir dir="${gen-folder}" />
|
||||
<mkdir dir="${out-folder}" />
|
||||
<mkdir dir="${out-classes}" />
|
||||
</target>
|
||||
|
||||
<!-- Generate the R.java file for this project's resources. -->
|
||||
<target name="resource-src" depends="dirs">
|
||||
<echo>Generating R.java / Manifest.java from the resources...</echo>
|
||||
<exec executable="${aapt}" failonerror="true">
|
||||
<arg value="package" />
|
||||
<arg value="-m" />
|
||||
<arg value="-J" />
|
||||
<arg path="${gen-folder}" />
|
||||
<arg value="-M" />
|
||||
<arg path="AndroidManifest.xml" />
|
||||
<arg value="-S" />
|
||||
<arg path="${resource-folder}" />
|
||||
<arg value="-I" />
|
||||
<arg path="${android-jar}" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<!-- Generate java classes from .aidl files. -->
|
||||
<target name="aidl" depends="dirs">
|
||||
<echo>Compiling aidl files into Java classes...</echo>
|
||||
<apply executable="${aidl}" failonerror="true">
|
||||
<arg value="-p${android-aidl}" />
|
||||
<arg value="-I${source-folder}" />
|
||||
<arg value="-o${gen-folder}" />
|
||||
<fileset dir="${source-folder}">
|
||||
<include name="**/*.aidl"/>
|
||||
</fileset>
|
||||
</apply>
|
||||
</target>
|
||||
|
||||
<!-- Compile this project's .java files into .class files. -->
|
||||
<!-- I2P add buildrouter -->
|
||||
<target name="compile" depends="buildrouter, resource-src, aidl">
|
||||
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
|
||||
destdir="${out-classes}"
|
||||
bootclasspathref="android.target.classpath">
|
||||
<src path="${source-folder}" />
|
||||
<src path="${gen-folder}" />
|
||||
<classpath>
|
||||
<fileset dir="${external-libs-folder}" includes="*.jar"/>
|
||||
<pathelement path="${main-out-classes}"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Convert this project's .class files into .dex files. -->
|
||||
<!-- I2P add hackcleanup -->
|
||||
<target name="dex" depends="compile, hackcleanup">
|
||||
<echo>Converting compiled files and external libraries into ${out-folder}/${dex-file}...</echo>
|
||||
<apply executable="${dx}" failonerror="true" parallel="true">
|
||||
<!-- I2P this is a bad sign that we need this -->
|
||||
<arg value="-JXmx256m" />
|
||||
<arg value="--dex" />
|
||||
<arg value="--output=${intermediate-dex-location}" />
|
||||
<arg path="${out-classes-location}" />
|
||||
<fileset dir="${external-libs-folder}" includes="*.jar"/>
|
||||
</apply>
|
||||
</target>
|
||||
|
||||
<!-- Put the project's resources into the output package file
|
||||
This actually can create multiple resource package in case
|
||||
Some custom apk with specific configuration have been
|
||||
declared in default.properties.
|
||||
-->
|
||||
<target name="package-resources">
|
||||
<echo>Packaging resources</echo>
|
||||
<aaptexec executable="${aapt}"
|
||||
command="package"
|
||||
manifest="AndroidManifest.xml"
|
||||
resources="${resource-folder}"
|
||||
assets="${asset-folder}"
|
||||
androidjar="${android-jar}"
|
||||
outfolder="${out-folder}"
|
||||
basename="${ant.project.name}" />
|
||||
</target>
|
||||
|
||||
<!-- Package the application and sign it with a debug key.
|
||||
This is the default target when building. It is used for debug. -->
|
||||
<target name="debug" depends="dex, package-resources">
|
||||
<apkbuilder
|
||||
outfolder="${out-folder}"
|
||||
basename="${ant.project.name}"
|
||||
signed="true"
|
||||
verbose="false">
|
||||
<file path="${intermediate-dex}" />
|
||||
<sourcefolder path="${source-folder}" />
|
||||
<jarfolder path="${external-libs-folder}" />
|
||||
<nativefolder path="${native-libs-folder}" />
|
||||
</apkbuilder>
|
||||
</target>
|
||||
|
||||
<!-- Package the application without signing it.
|
||||
This allows for the application to be signed later with an official publishing key. -->
|
||||
<target name="release" depends="dex, package-resources">
|
||||
<apkbuilder
|
||||
outfolder="${out-folder}"
|
||||
basename="${ant.project.name}"
|
||||
signed="false"
|
||||
verbose="false">
|
||||
<file path="${intermediate-dex}" />
|
||||
<sourcefolder path="${source-folder}" />
|
||||
<jarfolder path="${external-libs-folder}" />
|
||||
<nativefolder path="${native-libs-folder}" />
|
||||
</apkbuilder>
|
||||
<echo>All generated packages need to be signed with jarsigner before they are published.</echo>
|
||||
</target>
|
||||
|
||||
<!-- Install the package on the default emulator -->
|
||||
<target name="install" depends="debug">
|
||||
<echo>Installing ${out-debug-package} onto default emulator...</echo>
|
||||
<exec executable="${adb}" failonerror="true">
|
||||
<arg value="install" />
|
||||
<arg path="${out-debug-package}" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="reinstall" depends="debug">
|
||||
<echo>Installing ${out-debug-package} onto default emulator...</echo>
|
||||
<exec executable="${adb}" failonerror="true">
|
||||
<arg value="install" />
|
||||
<arg value="-r" />
|
||||
<arg path="${out-debug-package}" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<!-- Uinstall the package from the default emulator -->
|
||||
<target name="uninstall">
|
||||
<echo>Uninstalling ${application-package} from the default emulator...</echo>
|
||||
<exec executable="${adb}" failonerror="true">
|
||||
<arg value="uninstall" />
|
||||
<arg path="${application-package}" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="help">
|
||||
<!-- displays starts at col 13
|
||||
|13 80| -->
|
||||
<echo>Android Ant Build. Available targets:</echo>
|
||||
<echo> help: Displays this help.</echo>
|
||||
<echo> debug: Builds the application and sign it with a debug key.</echo>
|
||||
<echo> release: Builds the application. The generated apk file must be</echo>
|
||||
<echo> signed before it is published.</echo>
|
||||
<echo> install: Installs the debug package onto a running emulator or</echo>
|
||||
<echo> device. This can only be used if the application has </echo>
|
||||
<echo> not yet been installed.</echo>
|
||||
<echo> reinstall: Installs the debug package on a running emulator or</echo>
|
||||
<echo> device that already has the application.</echo>
|
||||
<echo> The signatures must match.</echo>
|
||||
<echo> uninstall: uninstall the application from a running emulator or</echo>
|
||||
<echo> device.</echo>
|
||||
</target>
|
||||
</project>
|
11
android/default.properties
Normal file
11
android/default.properties
Normal file
@ -0,0 +1,11 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "build.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-2
|
18
android/res/layout/main.xml
Normal file
18
android/res/layout/main.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World, I2PAndroid"
|
||||
/>
|
||||
<ImageView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/i2plogo"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
3
android/res/raw/logger_config
Normal file
3
android/res/raw/logger_config
Normal file
@ -0,0 +1,3 @@
|
||||
logger.defaultLevel=INFO
|
||||
logger.record.net.i2p.router.transport.FIFOBandwidthRefiller=ERROR
|
||||
logger.record.net.i2p.stat.Rate=ERROR
|
16
android/res/raw/router_config
Normal file
16
android/res/raw/router_config
Normal file
@ -0,0 +1,16 @@
|
||||
# initial router.config
|
||||
# temp directory
|
||||
i2p.dir.temp=/data/data/net.i2p.router/files/tmp
|
||||
i2p.dir.pid=/data/data/net.i2p.router/files/tmp
|
||||
# save memory
|
||||
prng.buffers=2
|
||||
router.decayingBloomFilterM=20
|
||||
stat.full=false
|
||||
i2np.udp.maxConnections=30
|
||||
# no I2CP
|
||||
i2p.dummyClientFacade=true
|
||||
# for now
|
||||
i2np.ntcp.enable=false
|
||||
# not on android
|
||||
i2np.upnp.enable=false
|
||||
routerconsole.geoip.enable=false
|
4
android/res/values/strings.xml
Normal file
4
android/res/values/strings.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">I2PAndroid</string>
|
||||
</resources>
|
142
android/src/net/i2p/router/I2PAndroid.java
Normal file
142
android/src/net/i2p/router/I2PAndroid.java
Normal file
@ -0,0 +1,142 @@
|
||||
package net.i2p.router;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.NotFoundException;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterLaunch;
|
||||
// import net.i2p.util.NativeBigInteger;
|
||||
|
||||
public class I2PAndroid extends Activity
|
||||
{
|
||||
static Context _context;
|
||||
private static final String DIR = "/data/data/net.i2p.router/files";
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
_context = this; // Activity extends Context
|
||||
debugStuff();
|
||||
initialize();
|
||||
// 300ms per run
|
||||
// 5x slower than java on my server and 50x slower than native on my server
|
||||
// NativeBigInteger.main(null);
|
||||
}
|
||||
|
||||
public void onRestart()
|
||||
{
|
||||
System.err.println("onRestart called");
|
||||
super.onRestart();
|
||||
}
|
||||
|
||||
public void onStart()
|
||||
{
|
||||
System.err.println("onStart called");
|
||||
super.onStart();
|
||||
RouterLaunch.main(null);
|
||||
System.err.println("Router.main finished");
|
||||
}
|
||||
|
||||
public void onResume()
|
||||
{
|
||||
System.err.println("onResume called");
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
public void onPause()
|
||||
{
|
||||
System.err.println("onPause called");
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
public void onStop()
|
||||
{
|
||||
System.err.println("onStop called");
|
||||
super.onStop();
|
||||
|
||||
// from routerconsole ContextHelper
|
||||
List contexts = RouterContext.listContexts();
|
||||
if ( (contexts == null) || (contexts.size() <= 0) )
|
||||
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
|
||||
RouterContext ctx = (RouterContext)contexts.get(0);
|
||||
|
||||
// shutdown() doesn't return so use shutdownGracefully()
|
||||
ctx.router().shutdownGracefully(Router.EXIT_HARD);
|
||||
System.err.println("shutdown complete");
|
||||
}
|
||||
|
||||
public void onDestroy()
|
||||
{
|
||||
System.err.println("onDestroy called");
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
public static Context getContext() {
|
||||
return _context;
|
||||
}
|
||||
|
||||
private void debugStuff() {
|
||||
System.err.println("java.io.tmpdir" + ": " + System.getProperty("java.io.tmpdir"));
|
||||
System.err.println("java.vendor" + ": " + System.getProperty("java.vendor"));
|
||||
System.err.println("java.version" + ": " + System.getProperty("java.version"));
|
||||
System.err.println("os.arch" + ": " + System.getProperty("os.arch"));
|
||||
System.err.println("os.name" + ": " + System.getProperty("os.name"));
|
||||
System.err.println("os.version" + ": " + System.getProperty("os.version"));
|
||||
System.err.println("user.dir" + ": " + System.getProperty("user.dir"));
|
||||
System.err.println("user.home" + ": " + System.getProperty("user.home"));
|
||||
System.err.println("user.name" + ": " + System.getProperty("user.name"));
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
// Until we can edit the router.config on the device,
|
||||
// copy it from the resource every time.
|
||||
// File f = new I2PFile("router.config");
|
||||
// if (!f.exists()) {
|
||||
copyResourceToFile(R.raw.router_config, "router.config");
|
||||
copyResourceToFile(R.raw.logger_config, "logger.config");
|
||||
copyResourceToFile(R.raw.blocklist_txt, "blocklist.txt");
|
||||
// }
|
||||
|
||||
// Set up the locations so Router and WorkingDir can find them
|
||||
System.setProperty("i2p.dir.base", DIR);
|
||||
System.setProperty("i2p.dir.config", DIR);
|
||||
System.setProperty("wrapper.logfile", DIR + "/wrapper.log");
|
||||
}
|
||||
|
||||
private void copyResourceToFile(int resID, String f) {
|
||||
InputStream in = null;
|
||||
FileOutputStream out = null;
|
||||
|
||||
System.err.println("Creating file " + f + " from resource");
|
||||
byte buf[] = new byte[4096];
|
||||
try {
|
||||
// Context methods
|
||||
in = getResources().openRawResource(resID);
|
||||
out = openFileOutput(f, 0);
|
||||
|
||||
int read = 0;
|
||||
while ( (read = in.read(buf)) != -1)
|
||||
out.write(buf, 0, read);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
} catch (Resources.NotFoundException nfe) {
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
163
android/src/net/i2p/util/LogWriter.java
Normal file
163
android/src/net/i2p/util/LogWriter.java
Normal file
@ -0,0 +1,163 @@
|
||||
package net.i2p.util;
|
||||
|
||||
/*
|
||||
* public domain
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* bridge to android logging
|
||||
*
|
||||
* @author zzz
|
||||
*/
|
||||
class LogWriter implements Runnable {
|
||||
private final static long CONFIG_READ_ITERVAL = 10 * 1000;
|
||||
private long _lastReadConfig = 0;
|
||||
private long _numBytesInCurrentFile = 0;
|
||||
private OutputStream _currentOut; // = System.out
|
||||
private int _rotationNum = -1;
|
||||
private String _logFilenamePattern;
|
||||
private File _currentFile;
|
||||
private LogManager _manager;
|
||||
|
||||
private boolean _write;
|
||||
|
||||
private LogWriter() { // nop
|
||||
}
|
||||
|
||||
public LogWriter(LogManager manager) {
|
||||
_manager = manager;
|
||||
}
|
||||
|
||||
public void stopWriting() {
|
||||
_write = false;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
_write = true;
|
||||
try {
|
||||
while (_write) {
|
||||
flushRecords();
|
||||
rereadConfig();
|
||||
}
|
||||
System.err.println("Done writing");
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error writing the logs: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void flushRecords() { flushRecords(true); }
|
||||
public void flushRecords(boolean shouldWait) {
|
||||
try {
|
||||
List records = _manager._removeAll();
|
||||
if (records == null) return;
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
LogRecord rec = (LogRecord) records.get(i);
|
||||
writeRecord(rec);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
} finally {
|
||||
if (shouldWait) {
|
||||
try {
|
||||
synchronized (this) {
|
||||
this.wait(10*1000);
|
||||
}
|
||||
} catch (InterruptedException ie) { // nop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String currentFile() {
|
||||
return _currentFile != null ? _currentFile.getAbsolutePath() : "uninitialized";
|
||||
}
|
||||
|
||||
private void rereadConfig() {
|
||||
long now = Clock.getInstance().now();
|
||||
if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
|
||||
_manager.rereadConfig();
|
||||
_lastReadConfig = now;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeRecord(LogRecord rec) {
|
||||
if (rec.getThrowable() == null)
|
||||
log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage());
|
||||
else
|
||||
log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage(), rec.getThrowable());
|
||||
}
|
||||
|
||||
public void log(int priority, Class src, String name, String threadName, String msg) {
|
||||
if (src != null) {
|
||||
String tag = src.getName();
|
||||
int dot = tag.lastIndexOf(".");
|
||||
if (dot >= 0)
|
||||
tag = tag.substring(dot + 1);
|
||||
android.util.Log.println(toAndroidLevel(priority),
|
||||
tag,
|
||||
'[' + threadName + "] " + msg);
|
||||
} else if (name != null)
|
||||
android.util.Log.println(toAndroidLevel(priority),
|
||||
name,
|
||||
'[' + threadName + "] " + msg);
|
||||
else
|
||||
android.util.Log.println(toAndroidLevel(priority),
|
||||
threadName, msg);
|
||||
}
|
||||
|
||||
public void log(int priority, Class src, String name, String threadName, String msg, Throwable t) {
|
||||
if (src != null) {
|
||||
String tag = src.getName();
|
||||
int dot = tag.lastIndexOf(".");
|
||||
if (dot >= 0)
|
||||
tag = tag.substring(dot + 1);
|
||||
android.util.Log.println(toAndroidLevel(priority),
|
||||
tag,
|
||||
'[' + threadName + "] " + msg +
|
||||
' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
|
||||
} else if (name != null)
|
||||
android.util.Log.println(toAndroidLevel(priority),
|
||||
name,
|
||||
'[' + threadName + "] " + msg +
|
||||
' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
|
||||
else
|
||||
android.util.Log.println(toAndroidLevel(priority),
|
||||
threadName,
|
||||
msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
|
||||
}
|
||||
|
||||
private static int toAndroidLevel(int level) {
|
||||
switch (level) {
|
||||
case Log.DEBUG:
|
||||
return android.util.Log.DEBUG;
|
||||
case Log.INFO:
|
||||
return android.util.Log.INFO;
|
||||
case Log.WARN:
|
||||
return android.util.Log.WARN;
|
||||
case Log.ERROR:
|
||||
case Log.CRIT:
|
||||
default:
|
||||
return android.util.Log.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String replace(String pattern, int num) {
|
||||
char c[] = pattern.toCharArray();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i = 0; i < c.length; i++) {
|
||||
if ( (c[i] != '#') && (c[i] != '@') )
|
||||
buf.append(c[i]);
|
||||
else
|
||||
buf.append(num);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
|
||||
<file>file:/usblv/NetBeansProjects/i2p.i2p/apps/BOB/src/net/i2p/BOB/TCPio.java</file>
|
||||
</open-files>
|
||||
</project-private>
|
||||
|
@ -50,7 +50,7 @@ public class DoCMDS implements Runnable {
|
||||
|
||||
// FIX ME
|
||||
// I need a better way to do versioning, but this will do for now.
|
||||
public static final String BMAJ = "00", BMIN = "00", BREV = "08", BEXT = "";
|
||||
public static final String BMAJ = "00", BMIN = "00", BREV = "0A", BEXT = "";
|
||||
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
|
||||
private Socket server;
|
||||
private Properties props;
|
||||
|
@ -60,20 +60,9 @@ public class I2Plistener implements Runnable {
|
||||
this._log = _log;
|
||||
this.socketManager = S;
|
||||
this.serverSocket = SS;
|
||||
// tgwatch = 1;
|
||||
this.lives = lives;
|
||||
}
|
||||
|
||||
private void rlock() throws Exception {
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
}
|
||||
|
||||
private void runlock() throws Exception {
|
||||
database.releaseReadLock();
|
||||
info.releaseReadLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply listen on I2P port, and thread connections
|
||||
*
|
||||
@ -83,34 +72,31 @@ public class I2Plistener implements Runnable {
|
||||
I2PSocket sessSocket = null;
|
||||
int conn = 0;
|
||||
try {
|
||||
die:
|
||||
{
|
||||
try {
|
||||
serverSocket.setSoTimeout(50);
|
||||
|
||||
while (lives.get()) {
|
||||
try {
|
||||
sessSocket = serverSocket.accept();
|
||||
g = true;
|
||||
} catch (ConnectException ce) {
|
||||
g = false;
|
||||
} catch (SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
if (g) {
|
||||
g = false;
|
||||
conn++;
|
||||
// toss the connection to a new thread.
|
||||
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
|
||||
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
|
||||
t.start();
|
||||
}
|
||||
try {
|
||||
serverSocket.setSoTimeout(50);
|
||||
|
||||
while (lives.get()) {
|
||||
try {
|
||||
sessSocket = serverSocket.accept();
|
||||
g = true;
|
||||
} catch (ConnectException ce) {
|
||||
g = false;
|
||||
} catch (SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
} catch (I2PException e) {
|
||||
// bad shit
|
||||
System.out.println("Exception " + e);
|
||||
if (g) {
|
||||
g = false;
|
||||
conn++;
|
||||
// toss the connection to a new thread.
|
||||
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
|
||||
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
|
||||
t.start();
|
||||
}
|
||||
|
||||
}
|
||||
} catch (I2PException e) {
|
||||
// bad shit
|
||||
System.out.println("Exception " + e);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
|
@ -104,10 +104,10 @@ public class MUXlisten implements Runnable {
|
||||
this.database.releaseReadLock();
|
||||
this.info.releaseReadLock();
|
||||
|
||||
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
|
||||
if (this.come_in) {
|
||||
this.listener = new ServerSocket(port, backlog, host);
|
||||
}
|
||||
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
|
||||
// I2PException, IOException, RuntimeException
|
||||
// To bad we can't just catch and enumerate....
|
||||
// } catch (I2PException e) {
|
||||
@ -141,8 +141,6 @@ public class MUXlisten implements Runnable {
|
||||
this.info.add("STARTING", new Boolean(false));
|
||||
this.info.releaseWriteLock();
|
||||
this.database.releaseWriteLock();
|
||||
// throw new Exception(e);
|
||||
// Debugging, I guess.
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -78,16 +78,20 @@ public class TCPio implements Runnable {
|
||||
* --Sponge
|
||||
*
|
||||
* Tested with 128 bytes, and there was no performance gain.
|
||||
* 8192 bytes did lower load average across many connections.
|
||||
* Should I raise it higer? The correct thing to do would be to
|
||||
* override... perhaps use NTCP, but I2P's streaming lib lacks
|
||||
* anything NTCP compatable.
|
||||
*
|
||||
* --Sponge
|
||||
*/
|
||||
|
||||
int b;
|
||||
byte a[] = new byte[1];
|
||||
byte a[] = new byte[8192];
|
||||
try {
|
||||
try {
|
||||
while (lives.get()) {
|
||||
b = Ain.read(a, 0, 1);
|
||||
b = Ain.read(a, 0, 8192);
|
||||
if (b > 0) {
|
||||
Aout.write(a, 0, b);
|
||||
} else if (b == 0) {
|
||||
|
@ -64,16 +64,6 @@ public class TCPlistener implements Runnable {
|
||||
this.lives = lives;
|
||||
}
|
||||
|
||||
private void rlock() throws Exception {
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
}
|
||||
|
||||
private void runlock() throws Exception {
|
||||
database.releaseReadLock();
|
||||
info.releaseReadLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply listen on TCP port, and thread connections
|
||||
*
|
||||
@ -81,30 +71,27 @@ public class TCPlistener implements Runnable {
|
||||
public void run() {
|
||||
boolean g = false;
|
||||
int conn = 0;
|
||||
Socket server = null;
|
||||
try {
|
||||
die:
|
||||
{
|
||||
try {
|
||||
Socket server = new Socket();
|
||||
listener.setSoTimeout(50); // We don't block, we cycle and check.
|
||||
while (lives.get()) {
|
||||
try {
|
||||
server = listener.accept();
|
||||
g = true;
|
||||
} catch (SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
if (g) {
|
||||
conn++;
|
||||
// toss the connection to a new thread.
|
||||
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
|
||||
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
|
||||
t.start();
|
||||
g = false;
|
||||
}
|
||||
try {
|
||||
listener.setSoTimeout(50); // We don't block, we cycle and check.
|
||||
while (lives.get()) {
|
||||
try {
|
||||
server = listener.accept();
|
||||
g = true;
|
||||
} catch (SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
if (g) {
|
||||
conn++;
|
||||
// toss the connection to a new thread.
|
||||
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
|
||||
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
|
||||
t.start();
|
||||
g = false;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -193,7 +193,8 @@ public class AddressBook {
|
||||
(! host.endsWith(".router.i2p")) &&
|
||||
(! host.endsWith(".console.i2p")) &&
|
||||
|
||||
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AAAA")) ||
|
||||
// null cert ends with AAAA but other zero-length certs would be AA
|
||||
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AA")) ||
|
||||
(dest.length() > MIN_DEST_LENGTH && dest.length() <= MAX_DEST_LENGTH)) &&
|
||||
dest.replaceAll("[a-zA-Z0-9~-]", "").length() == 0
|
||||
;
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
@ -39,6 +39,9 @@ import java.util.Map;
|
||||
* Utility class providing methods to parse and write files in config file
|
||||
* format, and subscription file format.
|
||||
*
|
||||
* TODO: Change file encoding from default to UTF-8?
|
||||
* Or switch to the DataHelper loadProps/storeProps methods?
|
||||
*
|
||||
* @author Ragnarok
|
||||
*/
|
||||
public class ConfigParser {
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
/**
|
||||
* A thread that waits five minutes, then runs the addressbook daemon.
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
import javax.servlet.GenericServlet;
|
||||
import javax.servlet.ServletConfig;
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
/**
|
||||
* A subscription to a remote address book.
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package addressbook;
|
||||
package net.i2p.addressbook;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
@ -6,11 +6,11 @@
|
||||
<web-app>
|
||||
<servlet>
|
||||
<servlet-name>addressbook</servlet-name>
|
||||
<servlet-class>addressbook.Servlet</servlet-class>
|
||||
<servlet-class>net.i2p.addressbook.Servlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>home</param-name>
|
||||
<param-value>./addressbook</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
</web-app>
|
||||
</web-app>
|
||||
|
@ -1 +1,7 @@
|
||||
# NOTE: This I2P config file must use UTF-8 encoding
|
||||
#
|
||||
# If you have a 'split' directory installation, with configuration
|
||||
# files in ~/.i2p (Linux) or %APPDATA%\I2P (Windows), be sure to
|
||||
# edit the file in the configuration directory, NOT the install directory.
|
||||
#
|
||||
i2psnark.dir=i2psnark
|
||||
|
@ -7,7 +7,6 @@ package org.klomp.snark;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PSession;
|
||||
|
@ -137,6 +137,7 @@ public class BitField
|
||||
return count >= size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
// Not very efficient
|
||||
|
@ -17,6 +17,7 @@ import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketEepGet;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
||||
import net.i2p.data.DataFormatException;
|
||||
@ -46,7 +47,7 @@ public class I2PSnarkUtil {
|
||||
private Map _opts;
|
||||
private I2PSocketManager _manager;
|
||||
private boolean _configured;
|
||||
private Set _shitlist;
|
||||
private final Set _shitlist;
|
||||
private int _maxUploaders;
|
||||
private int _maxUpBW;
|
||||
private int _maxConnections;
|
||||
@ -231,7 +232,13 @@ public class I2PSnarkUtil {
|
||||
if (rewrite)
|
||||
fetchURL = rewriteAnnounce(url);
|
||||
//_log.debug("Rewritten url [" + fetchURL + "]");
|
||||
EepGet get = new EepGet(_context, _shouldProxy, _proxyHost, _proxyPort, retries, out.getAbsolutePath(), fetchURL);
|
||||
//EepGet get = new EepGet(_context, _shouldProxy, _proxyHost, _proxyPort, retries, out.getAbsolutePath(), fetchURL);
|
||||
// Use our tunnel for announces and .torrent fetches too! Make sure we're connected first...
|
||||
if (!connected()) {
|
||||
if (!connect())
|
||||
return null;
|
||||
}
|
||||
EepGet get = new I2PSocketEepGet(_context, _manager, retries, out.getAbsolutePath(), fetchURL);
|
||||
if (get.fetch()) {
|
||||
_log.debug("Fetch successful [" + url + "]: size=" + out.length());
|
||||
return out;
|
||||
@ -327,6 +334,11 @@ public class I2PSnarkUtil {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** @param ot non-null */
|
||||
public void setOpenTrackerString(String ot) {
|
||||
_opts.put(PROP_OPENTRACKERS, ot);
|
||||
}
|
||||
|
||||
public String getOpenTrackerString() {
|
||||
String rv = (String) _opts.get(PROP_OPENTRACKERS);
|
||||
if (rv == null)
|
||||
|
@ -110,6 +110,7 @@ class Message
|
||||
dos.write(data, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
switch (type)
|
||||
|
@ -345,6 +345,7 @@ public class MetaInfo
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "MetaInfo[info_hash='" + hexencode(info_hash)
|
||||
|
@ -106,6 +106,7 @@ public class Peer implements Comparable
|
||||
/**
|
||||
* Returns the String representation of the peerID.
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if (peerID != null)
|
||||
@ -125,6 +126,7 @@ public class Peer implements Comparable
|
||||
/**
|
||||
* The hash code of a Peer is the hash code of the peerID.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return peerID.hashCode() ^ (2 << _id);
|
||||
@ -134,6 +136,7 @@ public class Peer implements Comparable
|
||||
* Two Peers are equal when they have the same PeerID.
|
||||
* All other properties are ignored.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof Peer)
|
||||
|
@ -41,7 +41,7 @@ class PeerConnectionOut implements Runnable
|
||||
private boolean quit;
|
||||
|
||||
// Contains Messages.
|
||||
private List sendQueue = new ArrayList();
|
||||
private final List sendQueue = new ArrayList();
|
||||
|
||||
private static long __id = 0;
|
||||
private long _id;
|
||||
|
@ -236,10 +236,21 @@ public class PeerCoordinator implements PeerListener
|
||||
{
|
||||
synchronized(peers)
|
||||
{
|
||||
return !halted && peers.size() < _util.getMaxConnections();
|
||||
return !halted && peers.size() < getMaxConnections();
|
||||
}
|
||||
}
|
||||
|
||||
/** reduce max if huge pieces to keep from ooming */
|
||||
private int getMaxConnections() {
|
||||
int size = metainfo.getPieceLength(0);
|
||||
int max = _util.getMaxConnections();
|
||||
if (size <= 1024*1024)
|
||||
return max;
|
||||
if (size <= 2*1024*1024)
|
||||
return (max + 1) / 2;
|
||||
return (max + 3) / 4;
|
||||
}
|
||||
|
||||
public boolean halted() { return halted; }
|
||||
|
||||
public void halt()
|
||||
@ -294,7 +305,7 @@ public class PeerCoordinator implements PeerListener
|
||||
peer.disconnect(false); // Don't deregister this connection/peer.
|
||||
}
|
||||
// This is already checked in addPeer() but we could have gone over the limit since then
|
||||
else if (peers.size() >= _util.getMaxConnections())
|
||||
else if (peers.size() >= getMaxConnections())
|
||||
{
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
|
||||
@ -350,7 +361,7 @@ public class PeerCoordinator implements PeerListener
|
||||
peersize = peers.size();
|
||||
// This isn't a strict limit, as we may have several pending connections;
|
||||
// thus there is an additional check in connected()
|
||||
need_more = (!peer.isConnected()) && peersize < _util.getMaxConnections();
|
||||
need_more = (!peer.isConnected()) && peersize < getMaxConnections();
|
||||
// Check if we already have this peer before we build the connection
|
||||
Peer old = peerIDInList(peer.getPeerID(), peers);
|
||||
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
|
||||
@ -378,7 +389,7 @@ public class PeerCoordinator implements PeerListener
|
||||
if (peer.isConnected())
|
||||
_log.info("Add peer already connected: " + peer);
|
||||
else
|
||||
_log.info("Connections: " + peersize + "/" + _util.getMaxConnections()
|
||||
_log.info("Connections: " + peersize + "/" + getMaxConnections()
|
||||
+ " not accepting extra peer: " + peer);
|
||||
}
|
||||
return false;
|
||||
|
@ -12,7 +12,7 @@ import java.util.Set;
|
||||
* from it there too)
|
||||
*/
|
||||
public class PeerCoordinatorSet {
|
||||
private Set _coordinators;
|
||||
private final Set _coordinators;
|
||||
|
||||
public PeerCoordinatorSet() {
|
||||
_coordinators = new HashSet();
|
||||
|
@ -107,6 +107,7 @@ public class PeerID implements Comparable
|
||||
/**
|
||||
* The hash code of a PeerID is the exclusive or of all id bytes.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return hash;
|
||||
@ -127,6 +128,7 @@ public class PeerID implements Comparable
|
||||
/**
|
||||
* Two PeerIDs are equal when they have the same id, address and port.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof PeerID)
|
||||
@ -171,6 +173,7 @@ public class PeerID implements Comparable
|
||||
* and address is the base64 dest (was the base64 hash of the dest) which
|
||||
* should match what the bytemonsoon tracker reports on its web pages.
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
int nonZero = 0;
|
||||
|
@ -151,7 +151,7 @@ public interface PeerListener
|
||||
*
|
||||
* @param state the PeerState for the peer
|
||||
*/
|
||||
void savePeerPartial(PeerState state);
|
||||
void savePeerPartial(PeerState state); /* FIXME Exporting non-public type through public API FIXME */
|
||||
|
||||
/**
|
||||
* Called when a peer has connected and there may be a partially
|
||||
@ -161,7 +161,7 @@ public interface PeerListener
|
||||
*
|
||||
* @return request (contains the partial data and valid length)
|
||||
*/
|
||||
Request getPeerPartial(BitField havePieces);
|
||||
Request getPeerPartial(BitField havePieces); /* FIXME Exporting non-public type through public API FIXME */
|
||||
|
||||
/** Mark a peer's requested pieces unrequested when it is disconnected
|
||||
* This prevents premature end game
|
||||
|
@ -20,13 +20,20 @@ public class Piece implements Comparable {
|
||||
return this.peers.size() - ((Piece)o).peers.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
try {
|
||||
if (o instanceof Piece) {
|
||||
if (o == null) return false;
|
||||
return this.id == ((Piece)o).id;
|
||||
} catch (ClassCastException cce) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 31 * hash + this.id;
|
||||
return hash;
|
||||
}
|
||||
|
||||
public int getId() { return this.id; }
|
||||
@ -36,6 +43,7 @@ public class Piece implements Comparable {
|
||||
public boolean isRequested() { return this.requested; }
|
||||
public void setRequested(boolean requested) { this.requested = requested; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(id);
|
||||
}
|
||||
|
@ -51,11 +51,13 @@ class Request
|
||||
throw new IndexOutOfBoundsException("Illegal Request " + toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return piece ^ off ^ len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof Request)
|
||||
@ -67,6 +69,7 @@ class Request
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "(" + piece + "," + off + "," + len + ")";
|
||||
|
@ -28,7 +28,6 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.StringTokenizer;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,6 +36,7 @@ public class SnarkShutdown extends I2PAppThread
|
||||
|
||||
private final ShutdownListener listener;
|
||||
|
||||
/* FIXME Exporting non-public type through public API FIXME */
|
||||
public SnarkShutdown(Storage storage,
|
||||
PeerCoordinator coordinator,
|
||||
ConnectionAcceptor acceptor,
|
||||
@ -49,6 +50,7 @@ public class SnarkShutdown extends I2PAppThread
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//Snark.debug("Shutting down...", Snark.NOTICE);
|
||||
|
@ -46,7 +46,7 @@ public class Storage
|
||||
private final StorageListener listener;
|
||||
private I2PSnarkUtil _util;
|
||||
|
||||
private BitField bitfield; // BitField to represent the pieces
|
||||
private /* FIXME final FIXME */ BitField bitfield; // BitField to represent the pieces
|
||||
private int needed; // Number of pieces needed
|
||||
private boolean _probablyComplete; // use this to decide whether to open files RO
|
||||
|
||||
@ -57,7 +57,8 @@ public class Storage
|
||||
|
||||
/** The default piece size. */
|
||||
private static final int MIN_PIECE_SIZE = 256*1024;
|
||||
public static final int MAX_PIECE_SIZE = 1024*1024;
|
||||
/** note that we start reducing max number of peer connections above 1MB */
|
||||
public static final int MAX_PIECE_SIZE = 2*1024*1024;
|
||||
/** The maximum number of pieces in a torrent. */
|
||||
public static final int MAX_PIECES = 10*1024;
|
||||
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;
|
||||
|
@ -81,6 +81,7 @@ public class TrackerClient extends I2PAppThread
|
||||
started = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (stop) throw new RuntimeException("Dont rerun me, create a copy");
|
||||
super.start();
|
||||
@ -109,6 +110,7 @@ public class TrackerClient extends I2PAppThread
|
||||
return !stop && _util.connected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
String infoHash = urlencode(meta.getInfoHash());
|
||||
@ -162,7 +164,7 @@ public class TrackerClient extends I2PAppThread
|
||||
try
|
||||
{
|
||||
if (!verifyConnected()) return;
|
||||
boolean started = false;
|
||||
boolean runStarted = false;
|
||||
boolean firstTime = true;
|
||||
int consecutiveFails = 0;
|
||||
Random r = new Random();
|
||||
@ -178,7 +180,7 @@ public class TrackerClient extends I2PAppThread
|
||||
if (firstTime) {
|
||||
delay = r.nextInt(30*1000);
|
||||
firstTime = false;
|
||||
} else if (completed && started)
|
||||
} else if (completed && runStarted)
|
||||
delay = 3*SLEEP*60*1000 + random;
|
||||
else if (coordinator.trackerProblems != null && ++consecutiveFails < MAX_CONSEC_FAILS)
|
||||
delay = INITIAL_SLEEP;
|
||||
@ -221,7 +223,7 @@ public class TrackerClient extends I2PAppThread
|
||||
Tracker tr = (Tracker)iter.next();
|
||||
if ((!stop) && (!tr.stop) &&
|
||||
(completed || coordinator.needPeers()) &&
|
||||
(event == COMPLETED_EVENT || System.currentTimeMillis() > tr.lastRequestTime + tr.interval))
|
||||
(event.equals(COMPLETED_EVENT) || System.currentTimeMillis() > tr.lastRequestTime + tr.interval))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -237,7 +239,7 @@ public class TrackerClient extends I2PAppThread
|
||||
tr.consecutiveFails = 0;
|
||||
if (tr.isPrimary)
|
||||
consecutiveFails = 0;
|
||||
started = true;
|
||||
runStarted = true;
|
||||
tr.started = true;
|
||||
|
||||
Set peers = info.getPeers();
|
||||
@ -296,7 +298,7 @@ public class TrackerClient extends I2PAppThread
|
||||
|
||||
// we could try and total the unique peers but that's too hard for now
|
||||
coordinator.trackerSeenPeers = maxSeenPeers;
|
||||
if (!started)
|
||||
if (!runStarted)
|
||||
_util.debug(" Retrying in one minute...", Snark.DEBUG);
|
||||
} // *** end of while loop
|
||||
} // try
|
||||
@ -311,9 +313,9 @@ public class TrackerClient extends I2PAppThread
|
||||
try
|
||||
{
|
||||
// try to contact everybody we can
|
||||
// We don't need I2CP connection for eepget
|
||||
// if (!verifyConnected()) return;
|
||||
// Don't try to restart I2CP connection just to say goodbye
|
||||
for (Iterator iter = trackers.iterator(); iter.hasNext(); ) {
|
||||
if (!verifyConnected()) return;
|
||||
Tracker tr = (Tracker)iter.next();
|
||||
if (tr.started && (!tr.stop) && tr.trackerProblems == null)
|
||||
doRequest(tr, infoHash, peerID, uploaded,
|
||||
@ -338,7 +340,7 @@ public class TrackerClient extends I2PAppThread
|
||||
+ "&uploaded=" + uploaded
|
||||
+ "&downloaded=" + downloaded
|
||||
+ "&left=" + left
|
||||
+ ((event != NO_EVENT) ? ("&event=" + event) : "");
|
||||
+ ((! event.equals(NO_EVENT)) ? ("&event=" + event) : "");
|
||||
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||
|
||||
tr.lastRequestTime = System.currentTimeMillis();
|
||||
|
@ -125,6 +125,7 @@ public class TrackerInfo
|
||||
return interval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if (failure_reason != null)
|
||||
|
@ -172,6 +172,7 @@ public class BEValue
|
||||
/** return the untyped value */
|
||||
public Object getValue() { return value; }
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String valueString;
|
||||
|
@ -27,7 +27,6 @@ import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import org.klomp.snark.I2PSnarkUtil;
|
||||
import org.klomp.snark.MetaInfo;
|
||||
import org.klomp.snark.Peer;
|
||||
import org.klomp.snark.Snark;
|
||||
@ -46,6 +45,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
|
||||
public static final String PROP_CONFIG_FILE = "i2psnark.configFile";
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig cfg) throws ServletException {
|
||||
super.init(cfg);
|
||||
_context = I2PAppContext.getGlobalContext();
|
||||
@ -59,11 +59,13 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
_manager.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
req.setCharacterEncoding("UTF-8");
|
||||
resp.setCharacterEncoding("UTF-8");
|
||||
resp.setContentType("text/html; charset=UTF-8");
|
||||
long stats[] = {0,0,0,0,0};
|
||||
/** dl, ul, down rate, up rate, peers, size */
|
||||
final long stats[] = {0,0,0,0,0,0};
|
||||
|
||||
String nonce = req.getParameter("nonce");
|
||||
if ( (nonce != null) && (nonce.equals(String.valueOf(_nonce))) )
|
||||
@ -83,8 +85,8 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("<meta http-equiv=\"refresh\" content=\"60;" + req.getRequestURI() + peerString + "\">\n");
|
||||
out.write(HEADER);
|
||||
out.write("</head><body>");
|
||||
out.write("<center><div class=\"page\"><table border=\"0\" width=\"100%\"><tr><td align=\"center\" class=\"snarkTitle\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\"I2PSnark (Manual Page Refresh)\"><img src=\"/themes/console/images/i2psnark.png\" alt=\"I2PSnark Anonymous BitTorrent Client\" border=\"0\" class=\"snarklogo\"></a></table>");
|
||||
out.write("<div class=\"snarknavbar\"><a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\" target=\"_blank\">Forum</a>\n");
|
||||
out.write("<center>");
|
||||
out.write("<div class=\"snarknavbar\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\"Refresh page\" class=\"snarkRefresh\">I2PSnark</a> <a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\" target=\"_blank\">Forum</a>\n");
|
||||
Map trackers = _manager.getTrackers();
|
||||
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
@ -94,10 +96,10 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if (e < 0)
|
||||
continue;
|
||||
baseURL = baseURL.substring(e + 1);
|
||||
out.write("<a href=\"" + baseURL + "\" class=\"snarkRefresh\" target=\"_blank\">" + name + "</a>");
|
||||
out.write(" <a href=\"" + baseURL + "\" class=\"snarkRefresh\" target=\"_blank\">" + name + "</a>");
|
||||
}
|
||||
out.write("</div>\n");
|
||||
out.write("<div class=\"mainsection\"><div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
|
||||
out.write("<div class=\"page\"><div class=\"mainsection\"><div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
|
||||
List msgs = _manager.getMessages();
|
||||
for (int i = msgs.size()-1; i >= 0; i--) {
|
||||
String msg = (String)msgs.get(i);
|
||||
@ -110,18 +112,18 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write(TABLE_HEADER);
|
||||
if (_manager.util().connected() && snarks.size() > 0) {
|
||||
if (peerParam != null)
|
||||
out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br />\n");
|
||||
out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br>\n");
|
||||
else
|
||||
out.write("(<a href=\"" + req.getRequestURI() + "?p=1" + "\">Show Peers</a>)<br />\n");
|
||||
out.write("(<a href=\"" + req.getRequestURI() + "?p=1" + "\">Show Peers</a>)<br>\n");
|
||||
}
|
||||
out.write(TABLE_HEADER2);
|
||||
out.write("<th align=\"left\">");
|
||||
out.write("<th align=\"center\">");
|
||||
if (_manager.util().connected())
|
||||
out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce +
|
||||
"\" title=\"Stop all torrents and the i2p tunnel\">Stop All</a>");
|
||||
"\" title=\"Stop all torrents and the I2P tunnel\">Stop All</a>");
|
||||
else if (snarks.size() > 0)
|
||||
out.write("<a href=\"" + uri + "?action=StartAll&nonce=" + _nonce +
|
||||
"\" title=\"Start all torrents and the i2p tunnel\">Start All</a>");
|
||||
"\" title=\"Start all torrents and the I2P tunnel\">Start All</a>");
|
||||
else
|
||||
out.write(" ");
|
||||
out.write("</th></tr></thead>\n");
|
||||
@ -135,7 +137,10 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write(TABLE_EMPTY);
|
||||
} else if (snarks.size() > 1) {
|
||||
out.write("<tfoot><tr>\n" +
|
||||
" <th align=\"left\" colspan=\"2\">Totals (" + snarks.size() + " torrents, " + stats[4] + " connected peers)</th>\n" +
|
||||
" <th align=\"left\" colspan=\"2\">Totals (" +
|
||||
snarks.size() + " torrents, " +
|
||||
DataHelper.formatSize(stats[5]) + "B, " +
|
||||
stats[4] + " connected peers)</th>\n" +
|
||||
" <th> </th>\n" +
|
||||
" <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
|
||||
" <th align=\"right\">" + formatSize(stats[1]) + "</th>\n" +
|
||||
@ -401,7 +406,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if (i > 0)
|
||||
filename = filename.substring(0, i);
|
||||
if (filename.length() > MAX_DISPLAYED_FILENAME_LENGTH)
|
||||
filename = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH) + "...";
|
||||
filename = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH) + "…";
|
||||
long total = snark.meta.getTotalLength();
|
||||
// Early typecast, avoid possibly overflowing a temp integer
|
||||
long remaining = (long) snark.storage.needed() * (long) snark.meta.getPieceLength(0);
|
||||
@ -429,6 +434,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
stats[2] += downBps;
|
||||
stats[3] += upBps;
|
||||
}
|
||||
stats[5] += total;
|
||||
|
||||
boolean isValid = snark.meta != null;
|
||||
boolean singleFile = snark.meta.getFiles() == null;
|
||||
@ -453,8 +459,8 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
statusString = "<a title=\"" + err + "\">TrackerErr (" + curPeers + "/" + knownPeers + " peers)";
|
||||
else {
|
||||
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
|
||||
err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "...";
|
||||
statusString = "TrackerErr<br />(" + err + ")";
|
||||
err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "…";
|
||||
statusString = "TrackerErr<br>(" + err + ")";
|
||||
}
|
||||
} else if (remaining <= 0) {
|
||||
if (isRunning && curPeers > 0 && !showPeers)
|
||||
@ -486,13 +492,13 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
|
||||
String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
|
||||
out.write("<tr class=\"" + rowClass + "\">");
|
||||
out.write("<td align=\"left\" class=\"snarkTorrentStatus " + rowClass + "\">");
|
||||
out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">");
|
||||
out.write(statusString + "</td>\n\t");
|
||||
out.write("<td align=\"left\" class=\"snarkTorrentName " + rowClass + "\">");
|
||||
|
||||
if (remaining == 0)
|
||||
out.write("<a href=\"" + _manager.linkPrefix() + snark.meta.getName()
|
||||
+ "\" title=\"Click to access completed downloaded..\">");
|
||||
+ "\" title=\"View file\">");
|
||||
out.write(filename);
|
||||
if (remaining == 0)
|
||||
out.write("</a>");
|
||||
@ -520,7 +526,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
}
|
||||
out.write("</td>\n\t");
|
||||
|
||||
out.write("<td align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">");
|
||||
out.write("<td align=\"center\" class=\"snarkTorrentETA " + rowClass + "\">");
|
||||
if(isRunning && remainingSeconds > 0)
|
||||
out.write(DataHelper.formatDuration(remainingSeconds*1000)); // (eta 6h)
|
||||
out.write("</td>\n\t");
|
||||
@ -540,7 +546,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if(isRunning)
|
||||
out.write(formatSize(upBps) + "ps");
|
||||
out.write("</td>\n\t");
|
||||
out.write("<td align=\"left\" class=\"snarkTorrentAction " + rowClass + "\">");
|
||||
out.write("<td align=\"center\" class=\"snarkTorrentAction " + rowClass + "\">");
|
||||
String parameters = "&nonce=" + _nonce + "&torrent=" + Base64.encode(snark.meta.getInfoHash());
|
||||
if (showPeers)
|
||||
parameters = parameters + "&p=1";
|
||||
@ -552,7 +558,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("<a href=\"" + uri + "?action=Start" + parameters
|
||||
+ "\" title=\"Start the torrent\">Start</a> ");
|
||||
out.write("<a href=\"" + uri + "?action=Remove" + parameters
|
||||
+ "\" title=\"Remove the torrent from the active list, deleting the .torrent file\">Remove</a><br />");
|
||||
+ "\" title=\"Remove the torrent from the active list, deleting the .torrent file\">Remove</a><br>");
|
||||
out.write("<a href=\"" + uri + "?action=Delete" + parameters
|
||||
+ "\" title=\"Delete the .torrent file and the associated data file(s)\">Delete</a> ");
|
||||
}
|
||||
@ -565,9 +571,9 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if (!peer.isConnected())
|
||||
continue;
|
||||
out.write("<tr class=\"" + rowClass + "\">");
|
||||
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
|
||||
out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">");
|
||||
out.write("</td>\n\t");
|
||||
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
|
||||
out.write("<td align=\"left\" class=\"snarkTorrentStatus " + rowClass + "\">");
|
||||
String ch = peer.toString().substring(0, 4);
|
||||
String client;
|
||||
if ("AwMD".equals(ch))
|
||||
@ -586,7 +592,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
client = "Robert";
|
||||
else
|
||||
client = "Unknown (" + ch + ')';
|
||||
out.write("<font size=-1>" + client + "</font> <tt>" + peer.toString().substring(5, 9) + "</tt>");
|
||||
out.write(client + " " + peer.toString().substring(5, 9));
|
||||
if (showDebug)
|
||||
out.write(" inactive " + (peer.getInactiveTime() / 1000) + "s");
|
||||
out.write("</td>\n\t");
|
||||
@ -595,12 +601,12 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
|
||||
float pct = (float) (100.0 * (float) peer.completed() / snark.meta.getPieces());
|
||||
if (pct == 100.0)
|
||||
out.write("<font size=-1>Seed</font>");
|
||||
out.write("Seed");
|
||||
else {
|
||||
String ps = String.valueOf(pct);
|
||||
if (ps.length() > 5)
|
||||
ps = ps.substring(0, 5);
|
||||
out.write("<font size=-1>" + ps + "%</font>");
|
||||
out.write(ps + "%");
|
||||
}
|
||||
out.write("</td>\n\t");
|
||||
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
|
||||
@ -609,14 +615,14 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if (remaining > 0) {
|
||||
if (peer.isInteresting() && !peer.isChoked()) {
|
||||
out.write("<font color=#008000>");
|
||||
out.write("<font size=-1>" + formatSize(peer.getDownloadRate()) + "ps</font></font>");
|
||||
out.write(formatSize(peer.getDownloadRate()) + "ps</font>");
|
||||
} else {
|
||||
out.write("<font color=#a00000><font size=-1><a title=\"");
|
||||
out.write("<font color=#a00000><a title=\"");
|
||||
if (!peer.isInteresting())
|
||||
out.write("Uninteresting\">");
|
||||
else
|
||||
out.write("Choked\">");
|
||||
out.write(formatSize(peer.getDownloadRate()) + "ps</a></font></font>");
|
||||
out.write(formatSize(peer.getDownloadRate()) + "ps</a></font>");
|
||||
}
|
||||
}
|
||||
out.write("</td>\n\t");
|
||||
@ -624,14 +630,14 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if (pct != 100.0) {
|
||||
if (peer.isInterested() && !peer.isChoking()) {
|
||||
out.write("<font color=#008000>");
|
||||
out.write("<font size=-1>" + formatSize(peer.getUploadRate()) + "ps</font></font>");
|
||||
out.write(formatSize(peer.getUploadRate()) + "ps</font>");
|
||||
} else {
|
||||
out.write("<font color=#a00000><font size=-1><a title=\"");
|
||||
out.write("<font color=#a00000><a title=\"");
|
||||
if (!peer.isInterested())
|
||||
out.write("Uninterested\">");
|
||||
else
|
||||
out.write("Choking\">");
|
||||
out.write(formatSize(peer.getUploadRate()) + "ps</a></font></font>");
|
||||
out.write(formatSize(peer.getUploadRate()) + "ps</a></font>");
|
||||
}
|
||||
}
|
||||
out.write("</td>\n\t");
|
||||
@ -653,14 +659,14 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("<span class=\"snarkNewTorrent\">\n");
|
||||
// *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
|
||||
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
|
||||
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" />\n");
|
||||
out.write("<div class=\"addtorrentsection\"><span class=\"snarkConfigTitle\">Add Torrent:</span><br />\n");
|
||||
out.write("From URL : <input type=\"text\" name=\"newURL\" size=\"80\" value=\"" + newURL + "\" /> \n");
|
||||
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
|
||||
out.write("<div class=\"addtorrentsection\"><span class=\"snarkConfigTitle\">Add Torrent</span><br>\n");
|
||||
out.write("From URL : <input type=\"text\" name=\"newURL\" size=\"80\" value=\"" + newURL + "\" > \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 />\n");
|
||||
out.write("<input type=\"submit\" value=\"Add torrent\" name=\"action\" /><br />\n");
|
||||
out.write("<span class=\"snarkAddInfo\">Alternately, you can copy .torrent files to " + _manager.getDataDir().getAbsolutePath() + "<br />\n");
|
||||
out.write("Removing that .torrent file will cause the torrent to stop.<br /></span>\n");
|
||||
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
|
||||
out.write("<input type=\"submit\" value=\"Add torrent\" name=\"action\" ><br>\n");
|
||||
out.write("<span class=\"snarkAddInfo\">Alternately, you can copy .torrent files to " + _manager.getDataDir().getAbsolutePath() + "<br>\n");
|
||||
out.write("Removing that .torrent file will cause the torrent to stop.<br></span>\n");
|
||||
out.write("</form>\n</span></div>");
|
||||
}
|
||||
|
||||
@ -673,12 +679,12 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("<div class=\"newtorrentsection\"><span class=\"snarkNewTorrent\">\n");
|
||||
// *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
|
||||
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
|
||||
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" />\n");
|
||||
out.write("<span class=\"snarkConfigTitle\">Create Torrent:</span><br />\n");
|
||||
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br />\n");
|
||||
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
|
||||
out.write("<span class=\"snarkConfigTitle\">Create Torrent</span><br>\n");
|
||||
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
|
||||
out.write("Data to seed: " + _manager.getDataDir().getAbsolutePath() + File.separatorChar
|
||||
+ "<input type=\"text\" name=\"baseFile\" size=\"20\" value=\"" + baseFile
|
||||
+ "\" title=\"File to seed (must be within the specified path)\" /><br />\n");
|
||||
+ "\" title=\"File to seed (must be within the specified path)\" ><br>\n");
|
||||
out.write("Tracker: <select name=\"announceURL\"><option value=\"\">Select a tracker</option>\n");
|
||||
Map trackers = _manager.getTrackers();
|
||||
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
|
||||
@ -692,8 +698,8 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
}
|
||||
out.write("</select>\n");
|
||||
out.write("or <input type=\"text\" name=\"announceURLOther\" size=\"50\" value=\"http://\" " +
|
||||
"title=\"Custom tracker URL\" /> ");
|
||||
out.write("<input type=\"submit\" value=\"Create torrent\" name=\"action\" />\n");
|
||||
"title=\"Custom tracker URL\" > ");
|
||||
out.write("<input type=\"submit\" value=\"Create torrent\" name=\"action\" >\n");
|
||||
out.write("</form>\n</span></div>");
|
||||
}
|
||||
|
||||
@ -707,16 +713,16 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
|
||||
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
|
||||
out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n");
|
||||
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" />\n");
|
||||
out.write("<span class=\"snarkConfigTitle\">Configuration:</span><br />\n");
|
||||
out.write("Data directory: <input type=\"text\" size=\"40\" name=\"dataDir\" value=\"" + dataDir + "\" ");
|
||||
out.write("title=\"Directory to store torrents and data\" disabled=\"true\" /> <i>(Edit i2psnark.config and restart to change)</i><br />\n");
|
||||
out.write("Auto start: <input type=\"checkbox\" name=\"autoStart\" value=\"true\" "
|
||||
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
|
||||
out.write("<span class=\"snarkConfigTitle\">Configuration</span><br>\n");
|
||||
out.write("<table border=\"0\"><tr><td>Data directory: <td><input type=\"text\" size=\"50\" name=\"dataDir\" value=\"" + dataDir + "\" ");
|
||||
out.write("title=\"Directory to store torrents and data\" disabled=\"true\" ><br><i>(Edit i2psnark.config and restart to change)</i><br>\n");
|
||||
out.write("<tr><td>Auto start: <td><input type=\"checkbox\" class=\"optbox\" name=\"autoStart\" value=\"true\" "
|
||||
+ (autoStart ? "checked " : "")
|
||||
+ "title=\"If true, automatically start torrents that are added\" />");
|
||||
+ "title=\"If true, automatically start torrents that are added\" >");
|
||||
//Auto add: <input type="checkbox" name="autoAdd" value="true" title="If true, automatically add torrents that are found in the data directory" />
|
||||
//Auto stop: <input type="checkbox" name="autoStop" value="true" title="If true, automatically stop torrents that are removed from the data directory" />
|
||||
//out.write("<br />\n");
|
||||
//out.write("<br>\n");
|
||||
/*
|
||||
out.write("Seed percentage: <select name=\"seedPct\" disabled=\"true\" >\n\t");
|
||||
if (seedPct <= 0)
|
||||
@ -731,28 +737,28 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("<option value=\"150\" selected=\"true\">150%</option>\n\t");
|
||||
else
|
||||
out.write("<option value=\"150\">150%</option>\n\t");
|
||||
out.write("</select><br />\n");
|
||||
out.write("</select><br>\n");
|
||||
*/
|
||||
out.write("Total uploader limit: <input type=\"text\" name=\"upLimit\" value=\""
|
||||
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" /> peers<br />\n");
|
||||
out.write("Up bandwidth limit: <input type=\"text\" name=\"upBW\" value=\""
|
||||
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" /> KBps <i>(Half <a href=\"/config.jsp\" target=\"blank\">available bandwidth</a> recommended.)</i><br />\n");
|
||||
out.write("<tr><td>Total uploader limit: <td><input type=\"text\" name=\"upLimit\" value=\""
|
||||
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" > peers<br>\n");
|
||||
out.write("<tr><td>Up bandwidth limit: <td><input type=\"text\" name=\"upBW\" value=\""
|
||||
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" > KBps <i>(Half <a href=\"/config.jsp\" target=\"blank\">available bandwidth</a> recommended.)</i><br>\n");
|
||||
|
||||
out.write("Use open trackers also: <input type=\"checkbox\" name=\"useOpenTrackers\" value=\"true\" "
|
||||
out.write("<tr><td>Use open trackers also: <td><input type=\"checkbox\" class=\"optbox\" name=\"useOpenTrackers\" value=\"true\" "
|
||||
+ (useOpenTrackers ? "checked " : "")
|
||||
+ "title=\"If true, uses open trackers in addition\" /> ");
|
||||
out.write("Announce URLs: <input type=\"text\" name=\"openTrackers\" value=\""
|
||||
+ openTrackers + "\" size=\"50\" /><br />\n");
|
||||
+ "title=\"If true, uses open trackers in addition\" > ");
|
||||
out.write("<tr><td>Open tracker announce URLs: <td><input type=\"text\" name=\"openTrackers\" value=\""
|
||||
+ openTrackers + "\" size=\"50\" ><br>\n");
|
||||
|
||||
//out.write("\n");
|
||||
out.write("EepProxy host: <input type=\"text\" name=\"eepHost\" value=\""
|
||||
+ _manager.util().getEepProxyHost() + "\" size=\"15\" /> ");
|
||||
out.write("port: <input type=\"text\" name=\"eepPort\" value=\""
|
||||
+ _manager.util().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br />\n");
|
||||
out.write("I2CP host: <input type=\"text\" name=\"i2cpHost\" value=\""
|
||||
+ _manager.util().getI2CPHost() + "\" size=\"15\" /> ");
|
||||
out.write("port: <input type=\"text\" name=\"i2cpPort\" value=\"" +
|
||||
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" /> <br />\n");
|
||||
//out.write("EepProxy host: <input type=\"text\" name=\"eepHost\" value=\""
|
||||
// + _manager.util().getEepProxyHost() + "\" size=\"15\" /> ");
|
||||
//out.write("port: <input type=\"text\" name=\"eepPort\" value=\""
|
||||
// + _manager.util().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br>\n");
|
||||
out.write("<tr><td>I2CP host: <td><input type=\"text\" name=\"i2cpHost\" value=\""
|
||||
+ _manager.util().getI2CPHost() + "\" size=\"15\" > ");
|
||||
out.write("<tr><td>I2CP port: <td><input type=\"text\" name=\"i2cpPort\" value=\"" +
|
||||
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" > <br>\n");
|
||||
StringBuilder opts = new StringBuilder(64);
|
||||
Map options = new TreeMap(_manager.util().getI2CPOptions());
|
||||
for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) {
|
||||
@ -761,10 +767,10 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
String val = (String)entry.getValue();
|
||||
opts.append(key).append('=').append(val).append(' ');
|
||||
}
|
||||
out.write("I2CP opts: <input type=\"text\" name=\"i2cpOpts\" size=\"80\" value=\""
|
||||
+ opts.toString() + "\" /><br />\n");
|
||||
out.write("<input type=\"submit\" value=\"Save configuration\" name=\"action\" />\n");
|
||||
out.write("</span>\n");
|
||||
out.write("<tr><td>I2CP options: <td><textarea name=\"i2cpOpts\" cols=\"60\" rows=\"1\" wrap=\"off\" >"
|
||||
+ opts.toString() + "</textarea><br>\n");
|
||||
out.write("<tr><td> <td><input type=\"submit\" value=\"Save configuration\" name=\"action\" >\n");
|
||||
out.write("</table></span>\n");
|
||||
out.write("</form></div>");
|
||||
}
|
||||
|
||||
@ -784,16 +790,16 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
"<head>\n" +
|
||||
"<title>I2PSnark - Anonymous BitTorrent Client</title>\n";
|
||||
|
||||
private static final String HEADER = "<link href=\"../themes/console/snark.css\" rel=\"stylesheet\" type=\"text/css\" />";
|
||||
private static final String HEADER = "<link href=\"../themes/console/snark.css\" rel=\"stylesheet\" type=\"text/css\" >";
|
||||
|
||||
|
||||
private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\" cellpadding=\"0 10px\">\n" +
|
||||
"<thead>\n" +
|
||||
"<tr><th align=\"left\">Status \n";
|
||||
"<tr><th align=\"center\">Status \n";
|
||||
|
||||
private static final String TABLE_HEADER2 = "</th>\n" +
|
||||
" <th align=\"left\">Torrent</th>\n" +
|
||||
" <th align=\"right\">ETA</th>\n" +
|
||||
" <th align=\"center\">ETA</th>\n" +
|
||||
" <th align=\"right\">Downloaded</th>\n" +
|
||||
" <th align=\"right\">Uploaded</th>\n" +
|
||||
" <th align=\"right\">Down Rate</th>\n" +
|
||||
|
@ -14,7 +14,7 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
class BufferLogger implements Logging {
|
||||
private final static Log _log = new Log(BufferLogger.class);
|
||||
private ByteArrayOutputStream _baos; // should be final and use a factory. LINT
|
||||
private ByteArrayOutputStream _baos; // FIXME should be final and use a factory. FIXME
|
||||
private boolean _ignore;
|
||||
|
||||
/**
|
||||
|
@ -373,7 +373,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
|
||||
privKeyFile = new File(args[2]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getAppDir(), args[2]);
|
||||
privKeyFile = new File(_context.getConfigDir(), args[2]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
|
||||
@ -422,7 +422,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
|
||||
privKeyFile = new File(args[2]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getAppDir(), args[2]);
|
||||
privKeyFile = new File(_context.getConfigDir(), args[2]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
|
||||
@ -481,7 +481,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
|
||||
privKeyFile = new File(args[3]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getAppDir(), args[3]);
|
||||
privKeyFile = new File(_context.getConfigDir(), args[3]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
|
||||
@ -877,7 +877,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
|
||||
File privKeyFile = new File(args[1]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getAppDir(), args[1]);
|
||||
privKeyFile = new File(_context.getConfigDir(), args[1]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
package net.i2p.i2ptunnel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
@ -66,7 +67,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
// private Object conLock = new Object();
|
||||
|
||||
/** List of Socket for those accept()ed but not yet started up */
|
||||
private List _waitingSockets = new ArrayList(); // should be final and use a factory. LINT
|
||||
private List _waitingSockets = new ArrayList(); // FIXME should be final and use a factory. FIXME
|
||||
/** How many connections will we allow to be in the process of being built at once? */
|
||||
private int _numConnectionBuilders;
|
||||
/** How long will we allow sockets to sit in the _waitingSockets map before killing them? */
|
||||
@ -114,7 +115,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
this.localPort = localPort;
|
||||
this.l = l;
|
||||
this.handlerName = handlerName + _clientId;
|
||||
this.privKeyFile = pkf;
|
||||
_ownDest = ownDest; // == ! shared client
|
||||
|
||||
|
||||
@ -124,6 +124,14 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
_context.statManager().createRateStat("i2ptunnel.client.manageTime", "How long it takes to accept a socket and fire it into an i2ptunnel runner (or queue it for the pool)?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
|
||||
|
||||
// normalize path so we can find it
|
||||
if (pkf != null) {
|
||||
File keyFile = new File(pkf);
|
||||
if (!keyFile.isAbsolute())
|
||||
keyFile = new File(_context.getConfigDir(), pkf);
|
||||
this.privKeyFile = keyFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
// no need to load the netDb with leaseSets for destinations that will never
|
||||
// be looked up
|
||||
tunnel.getClientOptions().setProperty("i2cp.dontPublishLeaseSet", "true");
|
||||
@ -277,6 +285,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
|
||||
return buildSocketManager(tunnel, null);
|
||||
}
|
||||
|
||||
/** @param pkf absolute path or null */
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel, String pkf) {
|
||||
Properties props = new Properties();
|
||||
props.putAll(tunnel.getClientOptions());
|
||||
|
@ -153,6 +153,7 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
|
||||
* create the default options (using the default timeout, etc)
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected I2PSocketOptions getDefaultOptions() {
|
||||
Properties defaultOpts = getTunnel().getClientOptions();
|
||||
if (!defaultOpts.contains(I2PSocketOptions.PROP_READ_TIMEOUT))
|
||||
@ -259,8 +260,8 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
|
||||
return;
|
||||
}
|
||||
|
||||
Destination dest = I2PTunnel.destFromName(destination);
|
||||
if (dest == null) {
|
||||
Destination clientDest = I2PTunnel.destFromName(destination);
|
||||
if (clientDest == null) {
|
||||
String str;
|
||||
byte[] header;
|
||||
if (usingWWWProxy)
|
||||
@ -276,7 +277,7 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
|
||||
return;
|
||||
}
|
||||
|
||||
I2PSocket i2ps = createI2PSocket(dest, getDefaultOptions());
|
||||
I2PSocket i2ps = createI2PSocket(clientDest, getDefaultOptions());
|
||||
byte[] data = null;
|
||||
byte[] response = null;
|
||||
if (usingWWWProxy)
|
||||
@ -344,7 +345,7 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
|
||||
if (targetRequest != null) {
|
||||
out.write(targetRequest.getBytes());
|
||||
if (usingWWWProxy)
|
||||
out.write(("<br>WWW proxy: " + wwwProxy).getBytes());
|
||||
out.write(("<br />WWW proxy: " + wwwProxy).getBytes());
|
||||
}
|
||||
out.write("</div>".getBytes());
|
||||
out.write("\n</body></html>\n".getBytes());
|
||||
|
@ -3,8 +3,10 @@
|
||||
*/
|
||||
package net.i2p.i2ptunnel;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@ -15,6 +17,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
@ -37,7 +40,7 @@ import net.i2p.util.Log;
|
||||
* or
|
||||
* $method $path $protocolVersion\nHost: $site
|
||||
* or
|
||||
* $method http://i2p/$site/$path $protocolVersion
|
||||
* $method http://i2p/$b64key/$path $protocolVersion
|
||||
* or
|
||||
* $method /$site/$path $protocolVersion
|
||||
* </pre>
|
||||
@ -55,6 +58,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
|
||||
private HashMap addressHelpers = new HashMap();
|
||||
|
||||
/**
|
||||
* These are backups if the xxx.ht error page is missing.
|
||||
*/
|
||||
|
||||
private final static byte[] ERR_REQUEST_DENIED =
|
||||
("HTTP/1.1 403 Access Denied\r\n"+
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"+
|
||||
@ -77,6 +84,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
"Could not find the following Destination:<BR><BR><div>")
|
||||
.getBytes();
|
||||
|
||||
/*****
|
||||
private final static byte[] ERR_TIMEOUT =
|
||||
("HTTP/1.1 504 Gateway Timeout\r\n"+
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"+
|
||||
@ -88,6 +96,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
"destination may have issues. Could not get a response from "+
|
||||
"the following Destination:<BR><BR>")
|
||||
.getBytes();
|
||||
*****/
|
||||
|
||||
private final static byte[] ERR_NO_OUTPROXY =
|
||||
("HTTP/1.1 503 Service Unavailable\r\n"+
|
||||
@ -108,11 +117,11 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
"The addresshelper link you followed specifies a different destination key "+
|
||||
"than a host entry in your host database. "+
|
||||
"Someone could be trying to impersonate another eepsite, "+
|
||||
"or people have given two eepsites identical names.<P/>"+
|
||||
"or people have given two eepsites identical names.<p>"+
|
||||
"You can resolve the conflict by considering which key you trust, "+
|
||||
"and either discarding the addresshelper link, "+
|
||||
"discarding the host entry from your host database, "+
|
||||
"or naming one of them differently.<P/>")
|
||||
"or naming one of them differently.<p>")
|
||||
.getBytes();
|
||||
|
||||
private final static byte[] ERR_BAD_PROTOCOL =
|
||||
@ -191,6 +200,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
* create the default options (using the default timeout, etc)
|
||||
* unused?
|
||||
*/
|
||||
@Override
|
||||
protected I2PSocketOptions getDefaultOptions() {
|
||||
Properties defaultOpts = getTunnel().getClientOptions();
|
||||
if (!defaultOpts.contains(I2PSocketOptions.PROP_READ_TIMEOUT))
|
||||
@ -207,6 +217,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
* create the default options (using the default timeout, etc)
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected I2PSocketOptions getDefaultOptions(Properties overrides) {
|
||||
Properties defaultOpts = getTunnel().getClientOptions();
|
||||
defaultOpts.putAll(overrides);
|
||||
@ -234,6 +245,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
OutputStream out = null;
|
||||
String targetRequest = null;
|
||||
boolean usingWWWProxy = false;
|
||||
boolean usingInternalServer = false;
|
||||
String currentProxy = null;
|
||||
long requestId = ++__requestId;
|
||||
try {
|
||||
@ -260,6 +272,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
int pos = line.indexOf(" ");
|
||||
if (pos == -1) break;
|
||||
method = line.substring(0, pos);
|
||||
// TODO use Java URL class to make all this simpler and more robust
|
||||
String request = line.substring(pos + 1);
|
||||
if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
|
||||
request = "http://i2p" + request;
|
||||
@ -305,8 +318,11 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
}
|
||||
}
|
||||
|
||||
// Quick hack for foo.bar.i2p
|
||||
if (host.toLowerCase().endsWith(".i2p")) {
|
||||
if (host.toLowerCase().equals("proxy.i2p")) {
|
||||
// so we don't do any naming service lookups
|
||||
destination = "proxy.i2p";
|
||||
usingInternalServer = true;
|
||||
} else if (host.toLowerCase().endsWith(".i2p")) {
|
||||
// Destination gets the host name
|
||||
destination = host;
|
||||
// Host becomes the destination key
|
||||
@ -374,22 +390,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
// Did addresshelper key conflict?
|
||||
if (ahelperConflict)
|
||||
{
|
||||
String str;
|
||||
byte[] header;
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "ahelper-conflict-header.ht")).getAbsolutePath(), 100, true);
|
||||
if (str != null) header = str.getBytes();
|
||||
else header = ERR_AHELPER_CONFLICT;
|
||||
|
||||
if (out != null) {
|
||||
// Fixme untranslated
|
||||
long alias = I2PAppContext.getGlobalContext().random().nextLong();
|
||||
String trustedURL = protocol + uriPath + urlEncoding;
|
||||
String conflictURL = protocol + alias + ".i2p/?" + initialFragments;
|
||||
byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
|
||||
out.write(header);
|
||||
out.write(("To visit the destination in your host database, click <a href=\"" + trustedURL + "\">here</a>. To visit the conflicting addresshelper link by temporarily giving it a random alias, click <a href=\"" + conflictURL + "\">here</a>.<P/>").getBytes());
|
||||
out.write("</div><div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());
|
||||
out.write(new Date().toString().getBytes());
|
||||
out.write("</i></div></body></html>\n".getBytes());
|
||||
out.flush();
|
||||
out.write(("To visit the destination in your host database, click <a href=\"" + trustedURL + "\">here</a>. To visit the conflicting addresshelper link by temporarily giving it a random alias, click <a href=\"" + conflictURL + "\">here</a>.<p></div>").getBytes());
|
||||
writeFooter(out);
|
||||
}
|
||||
s.close();
|
||||
return;
|
||||
@ -404,6 +414,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
}
|
||||
|
||||
line = method + " " + request.substring(pos);
|
||||
} else if (host.toLowerCase().equals("localhost") || host.equals("127.0.0.1")) {
|
||||
if (out != null) {
|
||||
out.write(getErrorPage("localhost", ERR_LOCALHOST));
|
||||
writeFooter(out);
|
||||
}
|
||||
s.close();
|
||||
return;
|
||||
} else if (host.indexOf(".") != -1) {
|
||||
// rebuild host
|
||||
host = host + ":" + port;
|
||||
@ -418,11 +435,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
_log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
|
||||
l.log("No HTTP outproxy found for the request.");
|
||||
if (out != null) {
|
||||
out.write(ERR_NO_OUTPROXY);
|
||||
out.write("<p /><i>Generated on: ".getBytes());
|
||||
out.write(new Date().toString().getBytes());
|
||||
out.write("</i></body></html>\n".getBytes());
|
||||
out.flush();
|
||||
out.write(getErrorPage("noproxy", ERR_NO_OUTPROXY));
|
||||
writeFooter(out);
|
||||
}
|
||||
s.close();
|
||||
return;
|
||||
@ -431,42 +445,29 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
usingWWWProxy = true;
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(getPrefix(requestId) + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
|
||||
} else if (host.toLowerCase().startsWith("localhost:")) {
|
||||
if (out != null) {
|
||||
out.write(ERR_LOCALHOST);
|
||||
out.write("<p /><i>Generated on: ".getBytes());
|
||||
out.write(new Date().toString().getBytes());
|
||||
out.write("</i></body></html>\n".getBytes());
|
||||
out.flush();
|
||||
}
|
||||
s.close();
|
||||
return;
|
||||
} else {
|
||||
request = request.substring(pos + 1);
|
||||
pos = request.indexOf("/");
|
||||
if (pos < 0) {
|
||||
l.log("Invalid request url [" + request + "]");
|
||||
if (out != null) {
|
||||
out.write(ERR_REQUEST_DENIED);
|
||||
out.write("<p /><i>Generated on: ".getBytes());
|
||||
out.write(new Date().toString().getBytes());
|
||||
out.write("</i></body></html>\n".getBytes());
|
||||
out.flush();
|
||||
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
|
||||
writeFooter(out);
|
||||
}
|
||||
s.close();
|
||||
return;
|
||||
}
|
||||
destination = request.substring(0, pos);
|
||||
line = method + " " + request.substring(pos);
|
||||
}
|
||||
} // end host name processing
|
||||
|
||||
boolean isValid = usingWWWProxy || isSupportedAddress(host, protocol);
|
||||
boolean isValid = usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
|
||||
if (!isValid) {
|
||||
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "notValid(" + host + ")");
|
||||
method = null;
|
||||
destination = null;
|
||||
break;
|
||||
} else if (!usingWWWProxy) {
|
||||
} else if ((!usingWWWProxy) && (!usingInternalServer)) {
|
||||
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "host=getHostName(" + destination + ")");
|
||||
host = getHostName(destination); // hide original host
|
||||
}
|
||||
@ -477,7 +478,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
_log.debug(getPrefix(requestId) + "HOST :" + host + ":");
|
||||
_log.debug(getPrefix(requestId) + "DEST :" + destination + ":");
|
||||
}
|
||||
|
||||
|
||||
// end first line processing
|
||||
|
||||
} else {
|
||||
if (lowercaseLine.startsWith("host: ") && !usingWWWProxy) {
|
||||
line = "Host: " + host;
|
||||
@ -509,14 +512,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
continue; // completely strip the line
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (line.length() == 0) {
|
||||
|
||||
String ok = getTunnel().getClientOptions().getProperty("i2ptunnel.gzip");
|
||||
boolean gzip = DEFAULT_GZIP;
|
||||
if (ok != null)
|
||||
gzip = Boolean.valueOf(ok).booleanValue();
|
||||
if (gzip) {
|
||||
if (gzip && !usingInternalServer) {
|
||||
// according to rfc2616 s14.3, this *should* force identity, even if
|
||||
// an explicit q=0 for gzip doesn't. tested against orion.i2p, and it
|
||||
// seems to work.
|
||||
@ -530,7 +533,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
} else {
|
||||
newRequest.append(line).append("\r\n"); // HTTP spec
|
||||
}
|
||||
}
|
||||
} // end header processing
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(getPrefix(requestId) + "NewRequest header: [" + newRequest.toString() + "]");
|
||||
|
||||
@ -538,13 +542,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
l.log("No HTTP method found in the request.");
|
||||
if (out != null) {
|
||||
if ("http://".equalsIgnoreCase(protocol))
|
||||
out.write(ERR_REQUEST_DENIED);
|
||||
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
|
||||
else
|
||||
out.write(ERR_BAD_PROTOCOL);
|
||||
out.write("<p /><i>Generated on: ".getBytes());
|
||||
out.write(new Date().toString().getBytes());
|
||||
out.write("</i></body></html>\n".getBytes());
|
||||
out.flush();
|
||||
out.write(getErrorPage("protocol", ERR_BAD_PROTOCOL));
|
||||
writeFooter(out);
|
||||
}
|
||||
s.close();
|
||||
return;
|
||||
@ -555,34 +556,29 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
|
||||
// Serve local proxy files (images, css linked from error pages)
|
||||
// Ignore all the headers
|
||||
if (destination.equals("proxy.i2p")) {
|
||||
if (usingInternalServer) {
|
||||
serveLocalFile(out, method, targetRequest);
|
||||
s.close();
|
||||
return;
|
||||
}
|
||||
|
||||
Destination dest = I2PTunnel.destFromName(destination);
|
||||
if (dest == null) {
|
||||
Destination clientDest = I2PTunnel.destFromName(destination);
|
||||
if (clientDest == null) {
|
||||
//l.log("Could not resolve " + destination + ".");
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Unable to resolve " + destination + " (proxy? " + usingWWWProxy + ", request: " + targetRequest);
|
||||
String str;
|
||||
byte[] header;
|
||||
boolean showAddrHelper = false;
|
||||
if (usingWWWProxy)
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfp-header.ht")).getAbsolutePath(), 100, true);
|
||||
header = getErrorPage("dnfp", ERR_DESTINATION_UNKNOWN);
|
||||
else if(ahelper != 0)
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfb-header.ht")).getAbsolutePath(), 100, true);
|
||||
header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
|
||||
else if (destination.length() == 60 && destination.endsWith(".b32.i2p"))
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnf-header.ht")).getAbsolutePath(), 100, true);
|
||||
header = getErrorPage("dnf", ERR_DESTINATION_UNKNOWN);
|
||||
else {
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfh-header.ht")).getAbsolutePath(), 100, true);
|
||||
header = getErrorPage("dnfh", ERR_DESTINATION_UNKNOWN);
|
||||
showAddrHelper = true;
|
||||
}
|
||||
if (str != null)
|
||||
header = str.getBytes();
|
||||
else
|
||||
header = ERR_DESTINATION_UNKNOWN;
|
||||
writeErrorMessage(header, out, targetRequest, usingWWWProxy, destination, showAddrHelper);
|
||||
s.close();
|
||||
return;
|
||||
@ -594,7 +590,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
// 1 == disconnect. see ConnectionOptions in the new streaming lib, which i
|
||||
// dont want to hard link to here
|
||||
//opts.setProperty("i2p.streaming.inactivityTimeoutAction", ""+1);
|
||||
I2PSocket i2ps = createI2PSocket(dest, getDefaultOptions(opts));
|
||||
I2PSocket i2ps = createI2PSocket(clientDest, getDefaultOptions(opts));
|
||||
byte[] data = newRequest.toString().getBytes("ISO-8859-1");
|
||||
Runnable onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
|
||||
I2PTunnelRunner runner = new I2PTunnelHTTPClientRunner(s, i2ps, sockLock, data, mySockets, onTimeout);
|
||||
@ -656,6 +652,64 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* foo => errordir/foo-header_xx.ht for lang xx, or errordir/foo-header.ht,
|
||||
* or the backup byte array on fail.
|
||||
*
|
||||
* .ht files must be UTF-8 encoded and use \r\n terminators so the
|
||||
* HTTP headers are conformant.
|
||||
* We can't use FileUtil.readFile() because it strips \r
|
||||
*
|
||||
* @return non-null
|
||||
*/
|
||||
private byte[] getErrorPage(String base, byte[] backup) {
|
||||
return getErrorPage(getTunnel().getContext(), base, backup);
|
||||
}
|
||||
|
||||
private static byte[] getErrorPage(I2PAppContext ctx, String base, byte[] backup) {
|
||||
File errorDir = new File(ctx.getBaseDir(), "docs");
|
||||
String lang = ctx.getProperty("routerconsole.lang", Locale.getDefault().getLanguage());
|
||||
if (lang != null && lang.length() > 0 && !lang.equals("en")) {
|
||||
File file = new File(errorDir, base + "-header_" + lang + ".ht");
|
||||
try {
|
||||
return readFile(file);
|
||||
} catch (IOException ioe) {
|
||||
// try the english version now
|
||||
}
|
||||
}
|
||||
File file = new File(errorDir, base + "-header.ht");
|
||||
try {
|
||||
return readFile(file);
|
||||
} catch (IOException ioe) {
|
||||
return backup;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] readFile(File file) throws IOException {
|
||||
FileInputStream fis = null;
|
||||
byte[] buf = new byte[512];
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
|
||||
try {
|
||||
int len = 0;
|
||||
fis = new FileInputStream(file);
|
||||
while ((len = fis.read(buf)) > 0) {
|
||||
baos.write(buf, 0, len);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
} finally {
|
||||
try { if (fis != null) fis.close(); } catch (IOException foo) {}
|
||||
}
|
||||
// we won't ever get here
|
||||
}
|
||||
|
||||
private static void writeFooter(OutputStream out) throws IOException {
|
||||
// the css is hiding this div for now, but we'll keep it here anyway
|
||||
out.write("<div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());
|
||||
out.write(new Date().toString().getBytes());
|
||||
out.write("</i></div></body></html>\n".getBytes());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
private static class OnTimeout implements Runnable {
|
||||
private Socket _socket;
|
||||
private OutputStream _out;
|
||||
@ -705,6 +759,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
out.write("</a>".getBytes());
|
||||
if (usingWWWProxy) out.write(("<br>WWW proxy: " + wwwProxy).getBytes());
|
||||
if (showAddrHelper) {
|
||||
// Fixme untranslated
|
||||
out.write("<br><br>Click a link below to look for an address helper by using a \"jump\" service:<br>".getBytes());
|
||||
for (int i = 0; i < jumpServers.length; i++) {
|
||||
// Skip jump servers we don't know
|
||||
@ -727,10 +782,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
}
|
||||
}
|
||||
}
|
||||
out.write("</div><div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());
|
||||
out.write(new Date().toString().getBytes());
|
||||
out.write("</i></div></body></html>\n".getBytes());
|
||||
out.flush();
|
||||
out.write("</div>".getBytes());
|
||||
writeFooter(out);
|
||||
}
|
||||
}
|
||||
|
||||
@ -742,16 +795,11 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
// _log.warn(getPrefix(requestId) + "Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex);
|
||||
if (out != null) {
|
||||
try {
|
||||
String str;
|
||||
byte[] header;
|
||||
if (usingWWWProxy)
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfp-header.ht")).getAbsolutePath(), 100, true);
|
||||
header = getErrorPage(I2PAppContext.getGlobalContext(), "dnfp", ERR_DESTINATION_UNKNOWN);
|
||||
else
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnf-header.ht")).getAbsolutePath(), 100, true);
|
||||
if (str != null)
|
||||
header = str.getBytes();
|
||||
else
|
||||
header = ERR_DESTINATION_UNKNOWN;
|
||||
header = getErrorPage(I2PAppContext.getGlobalContext(), "dnf", ERR_DESTINATION_UNKNOWN);
|
||||
writeErrorMessage(header, out, targetRequest, usingWWWProxy, wwwProxy, false);
|
||||
} catch (IOException ioe) {
|
||||
// static
|
||||
@ -841,6 +889,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
String type;
|
||||
if (filename.endsWith(".css"))
|
||||
type = "text/css";
|
||||
else if (filename.endsWith(".ico"))
|
||||
type = "image/x-icon";
|
||||
else if (filename.endsWith(".png"))
|
||||
type = "image/png";
|
||||
else if (filename.endsWith(".jpg"))
|
||||
|
@ -77,10 +77,10 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
||||
protected void clientConnectionRun(Socket s) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("got a connection.");
|
||||
Destination dest = pickDestination();
|
||||
Destination clientDest = pickDestination();
|
||||
I2PSocket i2ps = null;
|
||||
try {
|
||||
i2ps = createI2PSocket(dest);
|
||||
i2ps = createI2PSocket(clientDest);
|
||||
i2ps.setReadTimeout(readTimeout);
|
||||
StringBuilder expectedPong = new StringBuilder();
|
||||
Thread in = new I2PThread(new IrcInboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " in");
|
||||
|
@ -73,7 +73,7 @@ public class TunnelController implements Logging {
|
||||
|
||||
File keyFile = new File(getPrivKeyFile());
|
||||
if (!keyFile.isAbsolute())
|
||||
keyFile = new File(I2PAppContext.getGlobalContext().getAppDir(), getPrivKeyFile());
|
||||
keyFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), getPrivKeyFile());
|
||||
if (keyFile.exists()) {
|
||||
//log("Not overwriting existing private keys in " + keyFile.getAbsolutePath());
|
||||
return;
|
||||
|
@ -255,7 +255,7 @@ public class TunnelControllerGroup {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(cfgFile);
|
||||
fos.write(buf.toString().getBytes());
|
||||
fos.write(buf.toString().getBytes("UTF-8"));
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Config written to " + cfgFile.getPath());
|
||||
} catch (IOException ioe) {
|
||||
|
@ -55,7 +55,7 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
|
||||
I2PSocket destSock = serv.getDestinationI2PSocket(this);
|
||||
new I2PTunnelRunner(clientSock, destSock, sockLock, null, mySockets);
|
||||
} catch (SOCKSException e) {
|
||||
_log.error("Error from SOCKS connection: " + e.getMessage());
|
||||
_log.error("Error from SOCKS connection", e);
|
||||
closeSocket(s);
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,6 @@ public class Pinger implements Source, Runnable {
|
||||
|
||||
protected Sink sink;
|
||||
protected Thread thread;
|
||||
protected Object waitlock; // should be final and use a factory. LINT
|
||||
protected Object waitlock; // FIXME should be final and use a factory. FIXME
|
||||
protected boolean running;
|
||||
}
|
||||
|
@ -69,5 +69,5 @@ public class I2PSink implements Sink {
|
||||
protected boolean raw;
|
||||
protected I2PSession sess;
|
||||
protected Destination dest;
|
||||
protected I2PDatagramMaker maker; // should be final and use a factory. LINT
|
||||
protected I2PDatagramMaker maker; // FIXME should be final and use a factory. FIXME
|
||||
}
|
||||
|
@ -67,5 +67,5 @@ public class I2PSinkAnywhere implements Sink {
|
||||
protected boolean raw;
|
||||
protected I2PSession sess;
|
||||
protected Destination dest;
|
||||
protected I2PDatagramMaker maker; // should be final and use a factory. LINT
|
||||
protected I2PDatagramMaker maker; // FIXME should be final and use a factory. FIXME
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ import net.i2p.util.Log;
|
||||
|
||||
private ServerSocket ss;
|
||||
|
||||
private Object startLock = new Object();
|
||||
private final Object startLock = new Object();
|
||||
private boolean startRunning = false;
|
||||
|
||||
private byte[] pubkey;
|
||||
|
@ -1,3 +1,4 @@
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean" %><%
|
||||
String tun = request.getParameter("tunnel");
|
||||
if (tun != null) {
|
||||
|
@ -13,7 +13,7 @@
|
||||
%>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>I2PTunnel Webmanager - Edit</title>
|
||||
<title>I2P Tunnel Manager - Edit</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||
|
||||
@ -192,7 +192,7 @@
|
||||
|
||||
<div id="tunnelAdvancedNetworking" class="panel">
|
||||
<div class="header">
|
||||
<h4>Advanced networking options</h4>
|
||||
<h4>Advanced networking options</h4><br />
|
||||
<span class="comment">(NOTE: when this client proxy is configured to share tunnels, then these options are for all the shared proxy clients!)</span>
|
||||
</div>
|
||||
|
||||
@ -319,7 +319,7 @@
|
||||
|
||||
<div id="optionsField" class="rowItem">
|
||||
<label for="reduce" accesskey="c">
|
||||
<span class="accessKey">C</span>lose tunnels when idle: <i>Experimental</i>
|
||||
<span class="accessKey">C</span>lose tunnels when idle:
|
||||
</label>
|
||||
</div>
|
||||
<div id="portField" class="rowItem">
|
||||
@ -335,10 +335,10 @@
|
||||
<table border="0"><tr><!-- I give up -->
|
||||
<td><input value="1" type="radio" id="startOnLoad" name="newDest" title="New Destination"
|
||||
<%=(editBean.getNewDest(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
|
||||
<td valign="center">Enable
|
||||
<td>Enable
|
||||
<td><input value="0" type="radio" id="startOnLoad" name="newDest" title="New Destination"
|
||||
<%=(editBean.getNewDest(curTunnel) || editBean.getPersistentClientKey(curTunnel) ? "" : " checked=\"checked\"")%> class="tickbox" />
|
||||
<td valign="center">Disable
|
||||
<td>Disable
|
||||
</table>
|
||||
</div>
|
||||
<div id="portField" class="rowItem">
|
||||
@ -354,7 +354,7 @@
|
||||
|
||||
<div id="optionsField" class="rowItem">
|
||||
<label for="reduce" accesskey="c">
|
||||
<span class="accessKey">D</span>elay tunnel open until required: <i>Experimental</i>
|
||||
<span class="accessKey">D</span>elay tunnel open until required:
|
||||
</label>
|
||||
</div>
|
||||
<div id="portField" class="rowItem">
|
||||
@ -411,7 +411,8 @@
|
||||
<div class="header"></div>
|
||||
<div class="footer">
|
||||
<div class="toolbox">
|
||||
<span class="comment">NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted</span>
|
||||
<span class="comment">NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted.</span>
|
||||
<div class="separator"><hr /></div>
|
||||
<input type="hidden" value="true" name="removeConfirm" />
|
||||
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Save changes" title="Save Changes"><span class="accessKey">S</span>ave</button>
|
||||
<button id="controlDelete" <%=(editBean.allowJS() ? "onclick=\"if (!confirm('Are you sure you want to delete?')) { return false; }\" " : "")%>accesskey="D" class="control" type="submit" name="action" value="Delete this proxy" title="Delete this Proxy"><span class="accessKey">D</span>elete</button>
|
||||
|
@ -13,7 +13,7 @@
|
||||
%>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>I2PTunnel Webmanager - Edit</title>
|
||||
<title>I2P Tunnel Manager - Edit</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||
|
||||
@ -399,7 +399,8 @@
|
||||
<div class="header"></div>
|
||||
<div class="footer">
|
||||
<div class="toolbox">
|
||||
<span class="comment">NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted</span>
|
||||
<span class="comment">NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted.</span>
|
||||
<div class="separator"><hr /></div>
|
||||
<input type="hidden" value="true" name="removeConfirm" />
|
||||
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Save changes" title="Save Changes"><span class="accessKey">S</span>ave</button>
|
||||
<button id="controlDelete" <%=(editBean.allowJS() ? "onclick=\"if (!confirm('Are you sure you want to delete?')) { return false; }\" " : "")%>accesskey="D" class="control" type="submit" name="action" value="Delete this proxy" title="Delete this Proxy"><span class="accessKey">D</span>elete</button>
|
||||
|
@ -1,18 +1,23 @@
|
||||
<%
|
||||
// http://www.crazysquirrel.com/computing/general/form-encoding.jspx
|
||||
if (request.getCharacterEncoding() == null)
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.IndexBean"%><?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<jsp:useBean class="net.i2p.i2ptunnel.web.IndexBean" id="indexBean" scope="request" />
|
||||
<jsp:setProperty name="indexBean" property="*" />
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>I2PTunnel Webmanager - List</title>
|
||||
<title>I2P Tunnel Manager - List</title>
|
||||
|
||||
<meta htt
|
||||
p-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
||||
<link href="/themes/console/images/favicon.ico" type="image/x-icon" rel="shortcut icon" />
|
||||
|
||||
<% if (indexBean.allowCSS()) {
|
||||
%><link href="/themes/console/images/favicon.ico" type="image/x-icon" rel="shortcut icon" />
|
||||
<link href="<%=indexBean.getTheme()%>default.css" rel="stylesheet" type="text/css" />
|
||||
%><link href="<%=indexBean.getTheme()%>default.css" rel="stylesheet" type="text/css" />
|
||||
<link href="<%=indexBean.getTheme()%>i2ptunnel.css" rel="stylesheet" type="text/css" />
|
||||
<% }
|
||||
%>
|
||||
@ -106,7 +111,7 @@ p-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<a class="control" title="Test HTTP server through I2P" href="http://<%=indexBean.getDestHashBase32(curServer)%>.b32.i2p">Preview</a>
|
||||
<%
|
||||
} else if (indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
|
||||
%><span class="text">Base32 Address:<br><%=indexBean.getDestHashBase32(curServer)%>.b32.i2p</span>
|
||||
%><span class="text">Base32 Address:<br /><%=indexBean.getDestHashBase32(curServer)%>.b32.i2p</span>
|
||||
<%
|
||||
} else {
|
||||
%><span class="comment">No Preview</span>
|
||||
|
@ -109,6 +109,13 @@
|
||||
<target name="distclean" depends="clean">
|
||||
<echo message="Not actually deleting the jetty libs (since they're so large)" />
|
||||
</target>
|
||||
<target name="reallyclean" depends="distclean">
|
||||
<delete dir="./jettylib" />
|
||||
</target>
|
||||
<target name="totallyclean" depends="clean">
|
||||
<delete dir="./jettylib" />
|
||||
<delete file="${jetty.filename}" />
|
||||
</target>
|
||||
<target name="javadoc" >
|
||||
<available property="jetty.zip.available" file="${jetty.filename}" type="file" />
|
||||
<available property="jetty.zip.javadocExtracted" file="build/javadoc" type="dir" />
|
||||
|
@ -23,7 +23,8 @@
|
||||
<target name="compile" depends="depend">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" >
|
||||
<!-- half of this is deprecated classes so turn deprecation off -->
|
||||
<javac srcdir="./src" debug="true" deprecation="off" source="1.5" target="1.5" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" >
|
||||
<compilerarg line="${javac.compilerargs}" />
|
||||
</javac>
|
||||
</target>
|
||||
|
@ -15,6 +15,7 @@ import net.i2p.util.Log;
|
||||
* and pull from a queue populated by various threads (each of whom have their own
|
||||
* timeout)
|
||||
*
|
||||
* @deprecated use I2PServerSocketFull
|
||||
*/
|
||||
class I2PServerSocketImpl implements I2PServerSocket {
|
||||
private final static Log _log = new Log(I2PServerSocketImpl.class);
|
||||
|
@ -0,0 +1,242 @@
|
||||
package net.i2p.client.streaming;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.EepGet;
|
||||
import net.i2p.util.SocketTimeout;
|
||||
|
||||
/**
|
||||
* Fetch a URL using a socket from the supplied I2PSocketManager.
|
||||
* Hostname must resolve to an i2p destination - no routing to an outproxy.
|
||||
* Does not support response gzip decompression (unlike I2PTunnelHTTPProxy) (yet),
|
||||
* but of course there is still gzip at the I2CP layer.
|
||||
*
|
||||
* This is designed for Java apps such as bittorrent clients that wish to
|
||||
* do HTTP fetches and use other protocols on a single set of tunnels.
|
||||
* This may provide anonymity benefits over using the shared clients HTTP proxy,
|
||||
* preventing inadvertent outproxy usage, reduce resource usage by eliminating
|
||||
* a second set of tunnels, and eliminate the requirement to
|
||||
* to separately configure the proxy host and port.
|
||||
*
|
||||
* For additional documentation see the superclass.
|
||||
*
|
||||
* Supports http://example.i2p/blah
|
||||
* Supports http://B32KEY.b32.i2p/blah
|
||||
* Supports http://i2p/B64KEY/blah for compatibility with the eepproxy
|
||||
* Supports http://B64KEY/blah for compatibility with the eepproxy
|
||||
* Warning - does not support /eepproxy/blah, address helpers, http://B64KEY.i2p/blah,
|
||||
* or other odd things that may be found in the HTTP proxy.
|
||||
*
|
||||
* @author zzz
|
||||
*/
|
||||
public class I2PSocketEepGet extends EepGet {
|
||||
private I2PSocketManager _socketManager;
|
||||
/** this replaces _proxy in the superclass. Sadly, I2PSocket does not extend Socket. */
|
||||
private I2PSocket _socket;
|
||||
|
||||
public I2PSocketEepGet(I2PAppContext ctx, I2PSocketManager mgr, int numRetries, String outputFile, String url) {
|
||||
this(ctx, mgr, numRetries, -1, -1, outputFile, null, url);
|
||||
}
|
||||
|
||||
public I2PSocketEepGet(I2PAppContext ctx, I2PSocketManager mgr, int numRetries, long minSize, long maxSize,
|
||||
String outputFile, OutputStream outputStream, String url) {
|
||||
// we're using this constructor:
|
||||
// public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) {
|
||||
super(ctx, false, null, -1, numRetries, minSize, maxSize, outputFile, outputStream, url, true, null, null);
|
||||
_socketManager = mgr;
|
||||
_log = ctx.logManager().getLog(I2PSocketEepGet.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* We have to override this to close _socket, since we can't use _proxy in super as the I2PSocket.
|
||||
*/
|
||||
@Override
|
||||
public boolean fetch(long fetchHeaderTimeout, long totalTimeout, long inactivityTimeout) {
|
||||
boolean rv = super.fetch(fetchHeaderTimeout, totalTimeout, inactivityTimeout);
|
||||
if (_socket != null) {
|
||||
try {
|
||||
_socket.close();
|
||||
_socket = null;
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the address, get a socket from the I2PSocketManager supplied in the constructor,
|
||||
* and send the request.
|
||||
*
|
||||
* @param timeout ignored
|
||||
*/
|
||||
@Override
|
||||
protected void sendRequest(SocketTimeout timeout) throws IOException {
|
||||
if (_outputStream == null) {
|
||||
File outFile = new File(_outputFile);
|
||||
if (outFile.exists())
|
||||
_alreadyTransferred = outFile.length();
|
||||
}
|
||||
|
||||
if (_proxyIn != null) try { _proxyIn.close(); } catch (IOException ioe) {}
|
||||
if (_proxyOut != null) try { _proxyOut.close(); } catch (IOException ioe) {}
|
||||
if (_socket != null) try { _socket.close(); } catch (IOException ioe) {}
|
||||
|
||||
try {
|
||||
URL url = new URL(_actualURL);
|
||||
if ("http".equals(url.getProtocol())) {
|
||||
String host = url.getHost();
|
||||
int port = url.getPort();
|
||||
if (port != -1)
|
||||
throw new IOException("Ports not supported in i2p: " + _actualURL);
|
||||
|
||||
// HTTP Proxy compatibility http://i2p/B64KEY/blah
|
||||
// Rewrite the url to strip out the /i2p/,
|
||||
// as the naming service accepts B64KEY (but not B64KEY.i2p atm)
|
||||
if ("i2p".equals(host)) {
|
||||
String file = url.getFile();
|
||||
try {
|
||||
int slash = 1 + file.substring(1).indexOf("/");
|
||||
host = file.substring(1, slash);
|
||||
_actualURL = "http://" + host + file.substring(slash);
|
||||
} catch (IndexOutOfBoundsException ioobe) {
|
||||
throw new IOException("Bad /i2p/ format: " + _actualURL);
|
||||
}
|
||||
}
|
||||
|
||||
Destination dest = _context.namingService().lookup(host);
|
||||
if (dest == null)
|
||||
throw new UnknownHostException("Unknown or non-i2p host");
|
||||
|
||||
// Set the timeouts, using the other existing options in the socket manager
|
||||
// This currently duplicates what SocketTimeout is doing in EepGet,
|
||||
// but when that's ripped out of EepGet to use setsotimeout, we'll need this.
|
||||
Properties props = new Properties();
|
||||
props.setProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT, "" + CONNECT_TIMEOUT);
|
||||
props.setProperty(I2PSocketOptions.PROP_READ_TIMEOUT, "" + INACTIVITY_TIMEOUT);
|
||||
I2PSocketOptions opts = _socketManager.buildOptions(props);
|
||||
_socket = _socketManager.connect(dest, opts);
|
||||
} else {
|
||||
throw new IOException("Unsupported protocol: " + _actualURL);
|
||||
}
|
||||
} catch (MalformedURLException mue) {
|
||||
throw new IOException("Request URL is invalid: " + _actualURL);
|
||||
} catch (I2PException ie) {
|
||||
throw new IOException(ie.toString());
|
||||
}
|
||||
|
||||
_proxyIn = _socket.getInputStream();
|
||||
_proxyOut = _socket.getOutputStream();
|
||||
|
||||
// SocketTimeout doesn't take an I2PSocket, but no matter, because we
|
||||
// always close our socket in fetch() above.
|
||||
//timeout.setSocket(_socket);
|
||||
|
||||
String req = getRequest();
|
||||
_proxyOut.write(DataHelper.getUTF8(req));
|
||||
_proxyOut.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess we have to override this since
|
||||
* super doesn't strip the http://host from the GET line
|
||||
* which hoses some servers (opentracker)
|
||||
* HTTP proxy was kind enough to do this for us
|
||||
*/
|
||||
@Override
|
||||
protected String getRequest() throws IOException {
|
||||
StringBuilder buf = new StringBuilder(2048);
|
||||
URL url = new URL(_actualURL);
|
||||
String host = url.getHost();
|
||||
String path = url.getPath();
|
||||
String query = url.getQuery();
|
||||
if (query != null)
|
||||
path = path + '?' + query;
|
||||
if (!path.startsWith("/"))
|
||||
path = '/' + path;
|
||||
buf.append("GET ").append(path).append(" HTTP/1.1\r\n" +
|
||||
"Host: ").append(url.getHost()).append("\r\n");
|
||||
if (_alreadyTransferred > 0) {
|
||||
buf.append("Range: bytes=");
|
||||
buf.append(_alreadyTransferred);
|
||||
buf.append("-\r\n");
|
||||
}
|
||||
buf.append("Accept-Encoding: \r\n" +
|
||||
"Cache-control: no-cache\r\n" +
|
||||
"Pragma: no-cache\r\n" +
|
||||
"User-Agent: " + USER_AGENT + "\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* I2PSocketEepGet [-n #retries] [-t timeout] url
|
||||
* Uses I2CP at localhost:7654 with a single 1-hop tunnel each direction.
|
||||
* Tunnel build time not included in the timeout.
|
||||
*
|
||||
* This is just for testing, it will be commented out someday.
|
||||
* Real command line apps should use EepGet.main(),
|
||||
* which has more options, and you don't have to wait for tunnels to be built.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int numRetries = 0;
|
||||
long inactivityTimeout = INACTIVITY_TIMEOUT;
|
||||
String url = null;
|
||||
try {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i].equals("-n")) {
|
||||
numRetries = Integer.parseInt(args[i+1]);
|
||||
i++;
|
||||
} else if (args[i].equals("-t")) {
|
||||
inactivityTimeout = 1000 * Integer.parseInt(args[i+1]);
|
||||
i++;
|
||||
} else if (args[i].startsWith("-")) {
|
||||
usage();
|
||||
return;
|
||||
} else {
|
||||
url = args[i];
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (url == null) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
Properties opts = new Properties();
|
||||
opts.setProperty("i2cp.dontPublishLeaseSet", "true");
|
||||
opts.setProperty("inbound.quantity", "1");
|
||||
opts.setProperty("outbound.quantity", "1");
|
||||
opts.setProperty("inbound.length", "1");
|
||||
opts.setProperty("outbound.length", "1");
|
||||
opts.setProperty("inbound.nickname", "I2PSocketEepGet");
|
||||
I2PSocketManager mgr = I2PSocketManagerFactory.createManager(opts);
|
||||
if (mgr == null) {
|
||||
System.err.println("Error creating the socket manager");
|
||||
return;
|
||||
}
|
||||
I2PSocketEepGet get = new I2PSocketEepGet(I2PAppContext.getGlobalContext(),
|
||||
mgr, numRetries, suggestName(url), url);
|
||||
get.addStatusListener(get.new CLIStatusListener(1024, 40));
|
||||
get.fetch(inactivityTimeout, -1, inactivityTimeout);
|
||||
mgr.destroySocketManager();
|
||||
}
|
||||
|
||||
private static void usage() {
|
||||
System.err.println("I2PSocketEepGet [-n #retries] [-t timeout] url");
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ import net.i2p.util.Log;
|
||||
/**
|
||||
* Initial stub implementation for the socket
|
||||
*
|
||||
* @deprecated use I2PSocketFull
|
||||
*/
|
||||
class I2PSocketImpl implements I2PSocket {
|
||||
private final static Log _log = new Log(I2PSocketImpl.class);
|
||||
@ -29,7 +30,7 @@ class I2PSocketImpl implements I2PSocket {
|
||||
private Destination remote;
|
||||
private String localID;
|
||||
private String remoteID;
|
||||
private Object remoteIDWaiter = new Object();
|
||||
private final Object remoteIDWaiter = new Object();
|
||||
private I2PInputStream in;
|
||||
private I2POutputStream out;
|
||||
private I2PSocket.SocketErrorListener _socketErrorListener;
|
||||
@ -42,7 +43,7 @@ class I2PSocketImpl implements I2PSocket {
|
||||
private long _closedOn;
|
||||
private long _remoteIdSetTime;
|
||||
private I2PSocketOptions _options;
|
||||
private Object flagLock = new Object();
|
||||
private final Object flagLock = new Object();
|
||||
|
||||
/**
|
||||
* Whether the I2P socket has already been closed.
|
||||
@ -306,7 +307,7 @@ class I2PSocketImpl implements I2PSocket {
|
||||
//--------------------------------------------------
|
||||
private class I2PInputStream extends InputStream {
|
||||
private String streamName;
|
||||
private ByteCollector bc = new ByteCollector();
|
||||
private final ByteCollector bc = new ByteCollector();
|
||||
private boolean inStreamClosed = false;
|
||||
|
||||
private long readTimeout = -1;
|
||||
|
@ -13,7 +13,6 @@ import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PClientFactory;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -159,12 +158,12 @@ public class I2PSocketManagerFactory {
|
||||
}
|
||||
|
||||
private static I2PSocketManager createManager(I2PSession session, Properties opts, String name) {
|
||||
if (false) {
|
||||
I2PSocketManagerImpl mgr = new I2PSocketManagerImpl();
|
||||
mgr.setSession(session);
|
||||
//if (false) {
|
||||
//I2PSocketManagerImpl mgr = new I2PSocketManagerImpl();
|
||||
//mgr.setSession(session);
|
||||
//mgr.setDefaultOptions(new I2PSocketOptions());
|
||||
return mgr;
|
||||
} else {
|
||||
//return mgr;
|
||||
//} else {
|
||||
String classname = opts.getProperty(PROP_MANAGER, DEFAULT_MANAGER);
|
||||
if (classname != null) {
|
||||
try {
|
||||
@ -191,7 +190,7 @@ public class I2PSocketManagerFactory {
|
||||
} else {
|
||||
throw new IllegalStateException("No manager class specified");
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,11 +36,12 @@ import net.i2p.util.Log;
|
||||
* I2PSocketManager, it should not attempt to call I2PSession's setSessionListener
|
||||
* or receive any messages with its .receiveMessage
|
||||
*
|
||||
* @deprecated use I2PSocketManagerFull
|
||||
*/
|
||||
class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private /* final */ I2PSession _session;
|
||||
private /* FIXME final FIXME */ I2PSession _session;
|
||||
private I2PServerSocketImpl _serverSocket = null;
|
||||
private final Object lock = new Object(); // for locking socket lists
|
||||
private HashMap<String,I2PSocket> _outSockets;
|
||||
@ -672,6 +673,8 @@ class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener {
|
||||
* Ping the specified peer, returning true if they replied to the ping within
|
||||
* the timeout specified, false otherwise. This call blocks.
|
||||
*
|
||||
* @deprecated timeout is ignored - use I2PSocketManagerFull.ping()
|
||||
* @param timeoutMs ignored
|
||||
*/
|
||||
public boolean ping(Destination peer, long timeoutMs) {
|
||||
try {
|
||||
|
@ -53,7 +53,7 @@ public class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
_writeTimeout = getInt(opts, PROP_WRITE_TIMEOUT, DEFAULT_WRITE_TIMEOUT);
|
||||
}
|
||||
|
||||
protected int getInt(Properties opts, String name, int defaultVal) {
|
||||
protected static int getInt(Properties opts, String name, int defaultVal) {
|
||||
if (opts == null) return defaultVal;
|
||||
String val = opts.getProperty(name);
|
||||
if (val == null) {
|
||||
|
@ -16,9 +16,9 @@ net.i2p.client.streaming.I2PServerSocket#accept} method, which will provide an
|
||||
application wants to create a new stream to a peer, it should do so with the
|
||||
appropriate {@link net.i2p.client.streaming.I2PSocketManager#connect} call.</p>
|
||||
|
||||
<p>There is a simple pair of demo applications available as well - {@link
|
||||
net.i2p.client.streaming.StreamSinkServer} listens to a destination and dumps
|
||||
the data from all sockets it accepts to individual files, while {@link
|
||||
net.i2p.client.streaming.StreamSinkClient} connects to a particular destination
|
||||
<p>There is a simple pair of demo applications available as well -
|
||||
net.i2p.client.streaming.StreamSinkServer listens to a destination and dumps
|
||||
the data from all sockets it accepts to individual files, while
|
||||
net.i2p.client.streaming.StreamSinkClient connects to a particular destination
|
||||
and sends a specific amount of random data then disconnects.</p>
|
||||
</body></html>
|
||||
|
@ -117,7 +117,7 @@ public class StreamSinkClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire up the client. <code>Usage: StreamSinkClient [i2cpHost i2cpPort] sendSizeKB writeDelayMs serverDestFile [concurrentSends]</code> <br />
|
||||
* Fire up the client. <code>Usage: StreamSinkClient [i2cpHost i2cpPort] sendSizeKB writeDelayMs serverDestFile [concurrentSends]</code> <br>
|
||||
* <ul>
|
||||
* <li><b>sendSizeKB</b>: how many KB to send, or -1 for unlimited</li>
|
||||
* <li><b>writeDelayMs</b>: how long to wait between each .write (0 for no delay)</li>
|
@ -104,7 +104,7 @@ public class StreamSinkSend {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire up the client. <code>Usage: StreamSinkClient sendFile writeDelayMs serverDestFile</code> <br />
|
||||
* Fire up the client. <code>Usage: StreamSinkClient sendFile writeDelayMs serverDestFile</code> <br>
|
||||
* <ul>
|
||||
* <li><b>sendFile</b>: filename to send</li>
|
||||
* <li><b>writeDelayMs</b>: how long to wait between each .write (0 for no delay)</li>
|
@ -155,7 +155,7 @@ public class StreamSinkServer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire up the streaming server. <code>Usage: StreamSinkServer [i2cpHost i2cpPort] sinkDir ourDestFile [numHandlers]</code><br />
|
||||
* Fire up the streaming server. <code>Usage: StreamSinkServer [i2cpHost i2cpPort] sinkDir ourDestFile [numHandlers]</code><br>
|
||||
* <ul>
|
||||
* <li><b>sinkDir</b>: Directory to store received files in</li>
|
||||
* <li><b>ourDestFile</b>: filename to write our binary destination to</li>
|
17
apps/routerconsole/java/bmsg.sh
Normal file
17
apps/routerconsole/java/bmsg.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# Update messages_xx.po and messages_xx.class files,
|
||||
# from both java and jsp sources.
|
||||
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
|
||||
# zzz - public domain
|
||||
#
|
||||
|
||||
## launching sh.exe with -login parameter will open a shell with the current path always pointing to \bin\
|
||||
## need to cd into our orignal path - where we call sh.exe from.
|
||||
|
||||
cd $CALLFROM
|
||||
## echo $PWD
|
||||
|
||||
## except this everything is the same with bundle-message.sh
|
||||
## walking - public domain :-D
|
||||
|
||||
source bundle-messages.sh $PARAS
|
@ -73,11 +73,44 @@
|
||||
<delete dir="./tmpextract" />
|
||||
|
||||
<ant target="war" />
|
||||
|
||||
<!-- Update the messages_*.po files.
|
||||
We need to supply the bat file for windows, and then change the fail property to true -->
|
||||
<exec executable="sh" osfamily="unix" failifexecutionfails="false" >
|
||||
<arg value="./bundle-messages.sh" />
|
||||
</exec>
|
||||
<exec executable="sh" osfamily="mac" failifexecutionfails="false" >
|
||||
<arg value="./bundle-messages.sh" />
|
||||
</exec>
|
||||
<exec executable="cmd" osfamily="windows" failifexecutionfails="false" >
|
||||
<arg value="/c" />
|
||||
<arg value="bundle-messages.bat" />
|
||||
</exec>
|
||||
<!-- jar again to get the latest messages_*.class files -->
|
||||
<jar destfile="./build/routerconsole.jar" basedir="./build/obj" includes="**/*.class" update="true" />
|
||||
</target>
|
||||
<target name="poupdate" depends="build">
|
||||
<ant target="war" />
|
||||
<!-- Update the messages_*.po files.
|
||||
We need to supply the bat file for windows, and then change the fail property to true -->
|
||||
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
|
||||
<arg value="./bundle-messages.sh" />
|
||||
<arg value="-p" />
|
||||
</exec>
|
||||
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
|
||||
<arg value="./bundle-messages.sh" />
|
||||
<arg value="-p" />
|
||||
</exec>
|
||||
<exec executable="cmd" osfamily="windows" failifexecutionfails="true" >
|
||||
<arg value="/c" />
|
||||
<arg value="bundle-messages.bat" />
|
||||
<arg value="-p" />
|
||||
</exec>
|
||||
</target>
|
||||
<target name="war" depends="precompilejsp">
|
||||
<!-- Don't include the css in the war, the main build.xml will copy it to docs/themes/console/ -->
|
||||
<war destfile="build/routerconsole.war" webxml="../jsp/web-out.xml"
|
||||
basedir="../jsp/" excludes="web.xml, *.css, *.java, *.jsp, web-fragment.xml">
|
||||
basedir="../jsp/" excludes="web.xml, *.css, **/*.java, *.jsp, *.jsi, web-fragment.xml">
|
||||
</war>
|
||||
</target>
|
||||
<target name="precompilejsp" unless="precompilejsp.uptodate">
|
||||
@ -86,7 +119,36 @@
|
||||
<delete file="../jsp/web-out.xml" />
|
||||
<mkdir dir="../jsp/WEB-INF/" />
|
||||
<mkdir dir="../jsp/WEB-INF/classes" />
|
||||
|
||||
<!-- there are various jspc ant tasks, but they all seem a bit flakey -->
|
||||
<!--
|
||||
** Usage: jspc <options> <jsp files>
|
||||
** where jsp files is
|
||||
** -webapp <dir> A directory containing a web-app, whose JSP pages
|
||||
** will be processed recursively
|
||||
** or any number of
|
||||
** <file> A file to be parsed as a JSP page
|
||||
** where options include:
|
||||
** -help Print this help message
|
||||
** -v Verbose mode
|
||||
** -d <dir> Output Directory (default -Djava.io.tmpdir)
|
||||
** -l Outputs the name of the JSP page upon failure
|
||||
** -s Outputs the name of the JSP page upon success
|
||||
** -p <name> Name of target package (default org.apache.jsp)
|
||||
** -c <name> Name of target class name (only applies to first JSP page)
|
||||
** -mapped Generates separate write() calls for each HTML line in the JSP
|
||||
** -die[#] Generates an error return code (#) on fatal errors (default 1)
|
||||
** -uribase <dir> The uri directory compilations should be relative to
|
||||
** (default "/")
|
||||
** -uriroot <dir> Same as -webapp
|
||||
** -compile Compiles generated servlets
|
||||
** -webinc <file> Creates a partial servlet mappings in the file
|
||||
** -webxml <file> Creates a complete web.xml in the file
|
||||
** -ieplugin <clsid> Java Plugin classid for Internet Explorer
|
||||
** -classpath <path> Overrides java.class.path system property
|
||||
** -xpoweredBy Add X-Powered-By response header
|
||||
** -trimSpaces Trim spaces in template text between actions, directives
|
||||
-->
|
||||
<java classname="org.apache.jasper.JspC" fork="true" failonerror="true">
|
||||
<classpath>
|
||||
<pathelement location="../../jetty/jettylib/jasper-compiler.jar" />
|
||||
@ -115,6 +177,7 @@
|
||||
</java>
|
||||
|
||||
<javac debug="true" deprecation="on" source="1.5" target="1.5"
|
||||
encoding="UTF-8"
|
||||
destdir="../jsp/WEB-INF/classes/"
|
||||
srcdir="../jsp/WEB-INF/classes" includes="**/*.java">
|
||||
<compilerarg line="${javac.compilerargs}" />
|
||||
@ -123,6 +186,7 @@
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../systray/java/build/obj" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
<pathelement location="../../../installer/lib/wrapper/win32/wrapper.jar" />
|
||||
@ -132,10 +196,13 @@
|
||||
<pathelement location="../../../core/java/build/i2p.jar" />
|
||||
</classpath>
|
||||
</javac>
|
||||
|
||||
<!-- save these so we can run gettext on the generated java files later
|
||||
<delete>
|
||||
<fileset dir="../jsp/WEB-INF/" includes="**/*.java" />
|
||||
<fileset dir="../jsp/WEB-INF/" includes="**/*.jsp" />
|
||||
</delete>
|
||||
-->
|
||||
<copy file="../jsp/web.xml" tofile="../jsp/web-out.xml" />
|
||||
<loadfile property="jspc.web.fragment" srcfile="../jsp/web-fragment.xml" />
|
||||
<replace file="../jsp/web-out.xml">
|
||||
|
26
apps/routerconsole/java/bundle-messages.bat
Normal file
26
apps/routerconsole/java/bundle-messages.bat
Normal file
@ -0,0 +1,26 @@
|
||||
@echo off
|
||||
set Callfrom=%cd%
|
||||
set Paras=%1
|
||||
|
||||
rem before calling make sure you have msys and mingw 's "bin" path
|
||||
rem in your current searching path
|
||||
rem type "set path" to check
|
||||
if not exist ..\locale\*.only goto updateALL
|
||||
|
||||
rem put a messages_xx.only(eg messages_zh.only) into locale folder
|
||||
rem this script will only touch the po file(eg zh) you specified, leaving other po files untact.
|
||||
|
||||
for %%i in (..\locale\*.only) do set PO=%%~ni
|
||||
echo [Notice] Yu choose to Ony update the choosen file: %PO%.po
|
||||
for %%i in (..\locale\*.po) do if not %%~ni==%PO% ren %%i %%~ni.po-
|
||||
|
||||
call sh --login %cd%\bmsg.sh
|
||||
|
||||
for %%i in (..\locale\*.po-) do if not %%~ni==%PO% ren %%i %%~ni.po
|
||||
goto end
|
||||
|
||||
:updateALL
|
||||
call sh --login %cd%\bmsg.sh
|
||||
|
||||
:end
|
||||
echo End of Message Bundling
|
116
apps/routerconsole/java/bundle-messages.sh
Executable file
116
apps/routerconsole/java/bundle-messages.sh
Executable file
@ -0,0 +1,116 @@
|
||||
#
|
||||
# Update messages_xx.po and messages_xx.class files,
|
||||
# from both java and jsp sources.
|
||||
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
|
||||
#
|
||||
# usage:
|
||||
# bundle-messages.sh (generates the resource bundle from the .po file)
|
||||
# bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle)
|
||||
#
|
||||
# zzz - public domain
|
||||
#
|
||||
CLASS=net.i2p.router.web.messages
|
||||
TMPFILE=build/javafiles.txt
|
||||
export TZ=UTC
|
||||
|
||||
if [ "$1" = "-p" ]
|
||||
then
|
||||
POUPDATE=1
|
||||
fi
|
||||
|
||||
#
|
||||
# generate strings/Countries.java from ../../../installer/resources/countries.txt
|
||||
#
|
||||
CFILE=../../../installer/resources/countries.txt
|
||||
# add ../java/ so the refs will work in the po file
|
||||
JFILE=../java/build/Countries.java
|
||||
if [ $CFILE -nt $JFILE -o ! -s $JFILE ]
|
||||
then
|
||||
mkdir -p build
|
||||
echo '// Automatically generated pseudo-java for xgettext - do not edit' > $JFILE
|
||||
echo '// Translators may wish to translate a few of these, do not bother to translate all of them!!' >> $JFILE
|
||||
sed 's/..,\(..*\)/_("\1");/' $CFILE >> $JFILE
|
||||
fi
|
||||
|
||||
# list specific files in router/ here, so we don't scan the whole tree
|
||||
ROUTERFILES="\
|
||||
../../../router/java/src/net/i2p/router/RouterThrottleImpl.java \
|
||||
../../../router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java \
|
||||
../../../router/java/src/net/i2p/router/transport/TransportManager.java \
|
||||
../../../router/java/src/net/i2p/router/transport/GetBidsJob.java \
|
||||
../../../router/java/src/net/i2p/router/Blocklist.java \
|
||||
../../../router/java/src/net/i2p/router/transport/ntcp/EstablishState.java"
|
||||
|
||||
# add ../java/ so the refs will work in the po file
|
||||
JPATHS="../java/src ../jsp/WEB-INF ../java/strings $JFILE $ROUTERFILES"
|
||||
for i in ../locale/messages_*.po
|
||||
do
|
||||
# get language
|
||||
LG=${i#../locale/messages_}
|
||||
LG=${LG%.po}
|
||||
|
||||
if [ "$POUPDATE" = "1" ]
|
||||
then
|
||||
# make list of java files newer than the .po file
|
||||
find $JPATHS -name *.java -newer $i > $TMPFILE
|
||||
fi
|
||||
|
||||
if [ -s build/obj/net/i2p/router/web/messages_$LG.class -a \
|
||||
build/obj/net/i2p/router/web/messages_$LG.class -nt $i -a \
|
||||
! -s $TMPFILE ]
|
||||
then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$POUPDATE" = "1" ]
|
||||
then
|
||||
echo "Updating the $i file from the tags..."
|
||||
# extract strings from java and jsp files, and update messages.po files
|
||||
# translate calls must be one of the forms:
|
||||
# _("foo")
|
||||
# _x("foo")
|
||||
# intl._("foo")
|
||||
# intl.title("foo")
|
||||
# handler._("foo")
|
||||
# formhandler._("foo")
|
||||
# net.i2p.router.web.Messages.getString("foo")
|
||||
# In a jsp, you must use a helper or handler that has the context set.
|
||||
# To start a new translation, copy the header from an old translation to the new .po file,
|
||||
# then ant distclean updater.
|
||||
find $JPATHS -name *.java > $TMPFILE
|
||||
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 \
|
||||
--keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
|
||||
--keyword=handler._ --keyword=formhandler._ \
|
||||
--keyword=net.i2p.router.web.Messages.getString \
|
||||
-o ${i}t
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo 'Warning - xgettext failed, not updating translations'
|
||||
rm -f ${i}t
|
||||
break
|
||||
fi
|
||||
msgmerge -U --backup=none $i ${i}t
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo 'Warning - msgmerge failed, not updating translations'
|
||||
rm -f ${i}t
|
||||
break
|
||||
fi
|
||||
rm -f ${i}t
|
||||
# so we don't do this again
|
||||
touch $i
|
||||
fi
|
||||
|
||||
echo "Generating ${CLASS}_$LG ResourceBundle..."
|
||||
|
||||
# convert to class files in build/obj
|
||||
msgfmt --java -r $CLASS -l $LG -d build/obj $i
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo 'Warning - msgfmt failed, not updating translations'
|
||||
break
|
||||
fi
|
||||
done
|
||||
rm -f $TMPFILE
|
||||
# todo: return failure
|
||||
exit 0
|
@ -22,4 +22,26 @@ public class CSSHelper extends HelperBase {
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/** change default language for the router but don't save it */
|
||||
public void setLang(String lang) {
|
||||
if (lang != null && lang.length() > 0)
|
||||
_context.router().setConfigSetting(Messages.PROP_LANG, lang);
|
||||
}
|
||||
|
||||
/** needed for conditional css loads for zh */
|
||||
public String getLang() {
|
||||
return Messages.getLanguage(_context);
|
||||
}
|
||||
|
||||
/** translate the title and display consistently */
|
||||
public String title(String s) {
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
buf.append("<title>")
|
||||
.append(_("I2P Router Console"))
|
||||
.append(" - ")
|
||||
.append(_(s))
|
||||
.append("</title>");
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
@ -13,10 +13,11 @@ import java.util.Iterator;
|
||||
*
|
||||
*/
|
||||
public class ConfigAdvancedHandler extends FormHandler {
|
||||
private boolean _forceRestart;
|
||||
//private boolean _forceRestart;
|
||||
private boolean _shouldSave;
|
||||
private String _config;
|
||||
|
||||
@Override
|
||||
protected void processForm() {
|
||||
if (_shouldSave) {
|
||||
saveChanges();
|
||||
@ -26,7 +27,7 @@ public class ConfigAdvancedHandler extends FormHandler {
|
||||
}
|
||||
|
||||
public void setShouldsave(String moo) { _shouldSave = true; }
|
||||
public void setRestart(String moo) { _forceRestart = true; }
|
||||
//public void setRestart(String moo) { _forceRestart = true; }
|
||||
|
||||
public void setConfig(String val) {
|
||||
_config = val;
|
||||
@ -53,7 +54,7 @@ public class ConfigAdvancedHandler extends FormHandler {
|
||||
unsetKeys.remove(key);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
addFormError("Error updating the configuration (IOERROR) - please see the error logs");
|
||||
addFormError(_("Error updating the configuration - please see the error logs"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -65,15 +66,15 @@ public class ConfigAdvancedHandler extends FormHandler {
|
||||
|
||||
boolean saved = _context.router().saveConfig();
|
||||
if (saved)
|
||||
addFormNotice("Configuration saved successfully");
|
||||
addFormNotice(_("Configuration saved successfully"));
|
||||
else
|
||||
addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs");
|
||||
addFormNotice(_("Error saving the configuration (applied but not saved) - please see the error logs"));
|
||||
|
||||
if (_forceRestart) {
|
||||
addFormNotice("Performing a soft restart");
|
||||
_context.router().restart();
|
||||
addFormNotice("Soft restart complete");
|
||||
}
|
||||
//if (_forceRestart) {
|
||||
// addFormNotice("Performing a soft restart");
|
||||
// _context.router().restart();
|
||||
// addFormNotice("Soft restart complete");
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
public class ConfigAdvancedHelper extends HelperBase {
|
||||
public ConfigAdvancedHelper() {}
|
||||
|
@ -20,19 +20,25 @@ import org.mortbay.jetty.Server;
|
||||
* Saves changes to clients.config or webapps.config
|
||||
*/
|
||||
public class ConfigClientsHandler extends FormHandler {
|
||||
private Log _log;
|
||||
private Log configClient_log;
|
||||
private Map _settings;
|
||||
|
||||
public ConfigClientsHandler() {
|
||||
_log = ContextHelper.getContext(null).logManager().getLog(ConfigClientsHandler.class);
|
||||
configClient_log = ContextHelper.getContext(null).logManager().getLog(ConfigClientsHandler.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processForm() {
|
||||
if (_action.startsWith("Save Client")) {
|
||||
if (_action.equals(_("Save Client Configuration"))) {
|
||||
saveClientChanges();
|
||||
} else if (_action.startsWith("Save WebApp")) {
|
||||
return;
|
||||
}
|
||||
if (_action.equals(_("Save WebApp Configuration"))) {
|
||||
saveWebAppChanges();
|
||||
} else if (_action.startsWith("Start ")) {
|
||||
return;
|
||||
}
|
||||
// value
|
||||
if (_action.startsWith("Start ")) {
|
||||
String app = _action.substring(6);
|
||||
int appnum = -1;
|
||||
try {
|
||||
@ -42,10 +48,14 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
startClient(appnum);
|
||||
else
|
||||
startWebApp(app);
|
||||
} else if (_action.toLowerCase().startsWith("start<span class=hide> ") &&
|
||||
return;
|
||||
}
|
||||
// label (IE)
|
||||
String xStart = _("Start");
|
||||
if (_action.toLowerCase().startsWith(xStart + "<span class=hide> ") &&
|
||||
_action.toLowerCase().endsWith("</span>")) {
|
||||
// IE sucks
|
||||
String app = _action.substring(23, _action.length() - 7);
|
||||
String app = _action.substring(xStart.length() + 18, _action.length() - 7);
|
||||
int appnum = -1;
|
||||
try {
|
||||
appnum = Integer.parseInt(app);
|
||||
@ -55,7 +65,7 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
else
|
||||
startWebApp(app);
|
||||
} else {
|
||||
addFormError("Unsupported " + _action);
|
||||
addFormError(_("Unsupported") + ' ' + _action + '.');
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,22 +76,22 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
for (int cur = 0; cur < clients.size(); cur++) {
|
||||
ClientAppConfig ca = (ClientAppConfig) clients.get(cur);
|
||||
Object val = _settings.get(cur + ".enabled");
|
||||
if (! "webConsole".equals(ca.clientName))
|
||||
if (! ("webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName)))
|
||||
ca.disabled = val == null;
|
||||
}
|
||||
ClientAppConfig.writeClientAppConfig(_context, clients);
|
||||
addFormNotice("Client configuration saved successfully - restart required to take effect");
|
||||
addFormNotice(_("Client configuration saved successfully - restart required to take effect."));
|
||||
}
|
||||
|
||||
private void startClient(int i) {
|
||||
List clients = ClientAppConfig.getClientApps(_context);
|
||||
if (i >= clients.size()) {
|
||||
addFormError("Bad client index");
|
||||
addFormError(_("Bad client index."));
|
||||
return;
|
||||
}
|
||||
ClientAppConfig ca = (ClientAppConfig) clients.get(i);
|
||||
LoadClientAppsJob.runClient(ca.className, ca.clientName, LoadClientAppsJob.parseArgs(ca.args), _log);
|
||||
addFormNotice("Client " + ca.clientName + " started");
|
||||
LoadClientAppsJob.runClient(ca.className, ca.clientName, LoadClientAppsJob.parseArgs(ca.args), configClient_log);
|
||||
addFormNotice(_("Client") + ' ' + _(ca.clientName) + ' ' + _("started") + '.');
|
||||
}
|
||||
|
||||
private void saveWebAppChanges() {
|
||||
@ -98,7 +108,7 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
props.setProperty(name, "" + (val != null));
|
||||
}
|
||||
RouterConsoleRunner.storeWebAppProperties(props);
|
||||
addFormNotice("WebApp configuration saved successfully - restart required to take effect");
|
||||
addFormNotice(_("WebApp configuration saved successfully - restart required to take effect."));
|
||||
}
|
||||
|
||||
// Big hack for the moment, not using properties for directory and port
|
||||
@ -116,14 +126,14 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
path = new File(path, app + ".war");
|
||||
s.addWebApplication("/"+ app, path.getAbsolutePath()).start();
|
||||
// no passwords... initialize(wac);
|
||||
addFormNotice("WebApp <a href=\"/" + app + "/\">" + app + "</a> started");
|
||||
addFormNotice(_("WebApp") + " <a href=\"/" + app + "/\">" + _(app) + "</a> " + _("started") + '.');
|
||||
} catch (Exception ioe) {
|
||||
addFormError("Failed to start " + app + " " + ioe);
|
||||
addFormError(_("Failed to start") + ' ' + _(app) + " " + ioe + '.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
addFormError("Failed to find server");
|
||||
addFormError(_("Failed to find server."));
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.startup.ClientAppConfig;
|
||||
|
||||
public class ConfigClientsHelper extends HelperBase {
|
||||
@ -14,13 +13,14 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
|
||||
public String getForm1() {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<table border=\"1\">\n");
|
||||
buf.append("<tr><th>Client</th><th>Run at Startup?</th><th>Start Now</th><th>Class and arguments</th></tr>\n");
|
||||
buf.append("<table>\n");
|
||||
buf.append("<tr><th align=\"right\">" + _("Client") + "</th><th>" + _("Run at Startup?") + "</th><th>" + _("Start Now") + "</th><th align=\"left\">" + _("Class and arguments") + "</th></tr>\n");
|
||||
|
||||
List clients = ClientAppConfig.getClientApps(_context);
|
||||
for (int cur = 0; cur < clients.size(); cur++) {
|
||||
ClientAppConfig ca = (ClientAppConfig) clients.get(cur);
|
||||
renderForm(buf, ""+cur, ca.clientName, false, !ca.disabled, "webConsole".equals(ca.clientName),
|
||||
renderForm(buf, ""+cur, ca.clientName, false, !ca.disabled,
|
||||
"webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName),
|
||||
ca.className + ((ca.args != null) ? " " + ca.args : ""));
|
||||
}
|
||||
|
||||
@ -30,8 +30,8 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
|
||||
public String getForm2() {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<table border=\"1\">\n");
|
||||
buf.append("<tr><th>WebApp</th><th>Run at Startup?</th><th>Start Now</th><th>Description</th></tr>\n");
|
||||
buf.append("<table>\n");
|
||||
buf.append("<tr><th align=\"right\">" + _("WebApp") + "</th><th>" + _("Run at Startup?") + "</th><th>" + _("Start Now") + "</th><th align=\"left\">" + _("Description") + "</th></tr>\n");
|
||||
Properties props = RouterConsoleRunner.webAppProperties();
|
||||
Set keys = new TreeSet(props.keySet());
|
||||
for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
|
||||
@ -47,25 +47,25 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
}
|
||||
|
||||
private void renderForm(StringBuilder buf, String index, String name, boolean urlify, boolean enabled, boolean ro, String desc) {
|
||||
buf.append("<tr><td>");
|
||||
buf.append("<tr><td class=\"mediumtags\" align=\"right\" width=\"25%\">");
|
||||
if (urlify && enabled) {
|
||||
String link = "/";
|
||||
if (! RouterConsoleRunner.ROUTERCONSOLE.equals(name))
|
||||
link += name + "/";
|
||||
buf.append("<a href=\"").append(link).append("\">").append(name).append("</a>");
|
||||
buf.append("<a href=\"").append(link).append("\">").append(_(name)).append("</a>");
|
||||
} else {
|
||||
buf.append(name);
|
||||
buf.append(_(name));
|
||||
}
|
||||
buf.append("</td><td align=\"center\"><input type=\"checkbox\" name=\"").append(index).append(".enabled\" value=\"true\" ");
|
||||
buf.append("</td><td align=\"center\" width=\"10%\"><input type=\"checkbox\" class=\"optbox\" name=\"").append(index).append(".enabled\" value=\"true\" ");
|
||||
if (enabled) {
|
||||
buf.append("checked=\"true\" ");
|
||||
if (ro)
|
||||
buf.append("disabled=\"true\" ");
|
||||
}
|
||||
buf.append("/></td><td> ");
|
||||
buf.append("/></td><td align=\"center\" width=\"15%\">");
|
||||
if (!enabled) {
|
||||
buf.append("<button type=\"submit\" name=\"action\" value=\"Start ").append(index).append("\" >Start<span class=hide> ").append(index).append("</span></button>");
|
||||
buf.append("<button type=\"submit\" name=\"action\" value=\"Start ").append(index).append("\" >" + _("Start") + "<span class=hide> ").append(index).append("</span></button>");
|
||||
}
|
||||
buf.append(" </td><td>").append(desc).append("</td></tr>\n");
|
||||
buf.append("</td><td align=\"left\" width=\"50%\">").append(desc).append("</td></tr>\n");
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,52 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.util.ConvertToHash;
|
||||
|
||||
/**
|
||||
* Support additions via B64 Destkey, B64 Desthash, or blahblah.i2p
|
||||
* Support additions via B64 Destkey, B64 Desthash, blahblah.i2p, and others supported by ConvertToHash
|
||||
*/
|
||||
public class ConfigKeyringHandler extends FormHandler {
|
||||
private String _peer;
|
||||
private String _key;
|
||||
|
||||
@Override
|
||||
protected void processForm() {
|
||||
if ("Add key".equals(_action)) {
|
||||
if (_peer == null || _key == null) {
|
||||
addFormError("You must enter a destination and a key");
|
||||
if (_action == null) return;
|
||||
boolean adding = _action.equals(_("Add key"));
|
||||
if (adding || _action.equals(_("Delete key"))) {
|
||||
if (_peer == null)
|
||||
addFormError(_("You must enter a destination"));
|
||||
if (_key == null && adding)
|
||||
addFormError(_("You must enter a key"));
|
||||
if (_peer == null || (_key == null && adding))
|
||||
return;
|
||||
}
|
||||
Hash h = ConvertToHash.getHash(_peer);
|
||||
SessionKey sk = new SessionKey();
|
||||
try {
|
||||
sk.fromBase64(_key);
|
||||
} catch (DataFormatException dfe) {}
|
||||
if (h != null && h.getData() != null && sk.getData() != null) {
|
||||
_context.keyRing().put(h, sk);
|
||||
addFormNotice("Key for " + h.toBase64() + " added to keyring");
|
||||
} else {
|
||||
addFormError("Invalid destination or key");
|
||||
if (adding) {
|
||||
SessionKey sk = new SessionKey();
|
||||
try {
|
||||
sk.fromBase64(_key);
|
||||
} catch (DataFormatException dfe) {}
|
||||
if (h != null && h.getData() != null && sk.getData() != null) {
|
||||
_context.keyRing().put(h, sk);
|
||||
addFormNotice(_("Key for") + " " + h.toBase64() + " " + _("added to keyring"));
|
||||
} else {
|
||||
addFormError(_("Invalid destination or key"));
|
||||
}
|
||||
} else { // Delete
|
||||
if (h != null && h.getData() != null) {
|
||||
if (_context.keyRing().remove(h) != null)
|
||||
addFormNotice(_("Key for") + " " + h.toBase64() + " " + _("removed from keyring"));
|
||||
else
|
||||
addFormNotice(_("Key for") + " " + h.toBase64() + " " + _("not found in keyring"));
|
||||
} else {
|
||||
addFormError(_("Invalid destination"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addFormError("Unsupported");
|
||||
addFormError(_("Unsupported"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
public class ConfigKeyringHelper extends HelperBase {
|
||||
public ConfigKeyringHelper() {}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user