Compare commits

..

212 Commits

Author SHA1 Message Date
zzz
656670919d 0.8.3 2011-01-24 14:55:34 +00:00
zzz
bf99b04e0a cleanups after review, ticket 390 2011-01-24 13:20:06 +00:00
duck
4191eb98b0 Dutch translation updated (thanks KwukDuck) 2011-01-22 12:12:14 +00:00
z3d
1eec4484fd Light consistency tweak. 2011-01-22 08:10:01 +00:00
z3d
dc0c97c0ae Multifarious light tweaks. 2011-01-22 07:16:42 +00:00
z3d
a71372c679 TUnnel Manager: light button consistency fix. 2011-01-22 03:14:46 +00:00
z3d
cb2ce5ea29 Classic adjustment. 2011-01-22 03:03:42 +00:00
z3d
b3f8025393 TUnnel Manager light festooneries. 2011-01-22 02:22:36 +00:00
z3d
809bb59c9d Tunnel Manager light tweaks. 2011-01-22 01:51:53 +00:00
z3d
61456ba57e merge of '02fcc2f7749bae7a3ec47e06df2e87b744f859d9'
and '2a04fb3507bc56975b251f740976304cb2801283'
2011-01-21 14:13:49 +00:00
z3d
d05b02de13 Light Chinese finessing. 2011-01-21 12:52:42 +00:00
z3d
a4d270fa63 Light consistency tweaks. 2011-01-21 12:05:23 +00:00
z3d
a946af721e Light tabulatory tweaks. 2011-01-21 04:29:06 +00:00
hiddenz
568f242998 i2ptunnel: remove dup in russian translation 2011-01-21 03:47:03 +00:00
duck
9338196c30 Update Dutch translations 2011-01-20 21:23:00 +00:00
zzz
90fc3b0e57 fix XML comment-in-comment thx KillYourTV 2011-01-20 15:14:56 +00:00
z3d
08de93e7ef Light relief. 2011-01-20 10:29:10 +00:00
z3d
96593c7287 Light spice. 2011-01-20 10:08:07 +00:00
z3d
471ddaa209 Light chinese bite. 2011-01-20 09:57:20 +00:00
z3d
17946fbfab Light tweak, consistency fix. 2011-01-20 09:48:05 +00:00
z3d
22108f2c58 Light tweak. 2011-01-19 22:56:09 +00:00
z3d
2a7bb5b550 Midnight and light cleanups/tweaks. 2011-01-19 22:49:43 +00:00
hiddenz
ae00ec5dd6 routerconsole: update russian translation 2011-01-17 20:38:27 +00:00
hiddenz
f9384d627c readme_ru.html: fix link to anchor 2011-01-17 20:37:13 +00:00
hiddenz
bbb731af6c i2ptunnel: update russian translation 2011-01-17 19:37:12 +00:00
hiddenz
2ea05f01eb Fix typo 2011-01-17 19:26:41 +00:00
hiddenz
99405b7dff readme_ru.html: sync with english version 2011-01-17 18:52:24 +00:00
zzz
5a1027c5ed * UPnP:
- Change all log errors to warns (tickets #76, #95, #120)
      - Double socket soTimeout to 2 seconds
2011-01-16 15:31:45 +00:00
zzz
0ed88c5686 * UDP: Prevent rare startup NPE 2011-01-16 15:30:41 +00:00
zzz
32b817f9b1 allow editing of console args 2011-01-16 15:30:04 +00:00
zzz
04d04d0169 add some HTTP headers in the view servlets 2011-01-15 22:23:57 +00:00
z3d
d4a717e6b6 Console themes: Fix for http://trac.i2p2.i2p/ticket/359 2011-01-15 14:49:15 +00:00
z3d
f7df15fd5d Light tweaks. 2011-01-15 05:48:45 +00:00
z3d
29dfa77bce Tunnelmanager light finesse. 2011-01-15 05:39:03 +00:00
z3d
02fbd7f9d6 Light touch. 2011-01-15 05:05:06 +00:00
z3d
c453dd0e34 Console/tunnelmanager: light theme adulteration. 2011-01-15 04:09:53 +00:00
z3d
8b8a3a4a60 Light tweaks. 2011-01-14 12:55:26 +00:00
z3d
8b664fe2a1 merge of '0c3129e1443b3c155a4e5e06e008fa40a89776a3'
and 'fe23acdcae4f7bace1f6ceb4823a13271fe37207'
2011-01-14 12:28:32 +00:00
z3d
50a6a81706 Light tweaks. 2011-01-14 12:12:19 +00:00
z3d
9944dc0696 Console: light theme, borderline tweak. 2011-01-14 06:16:04 +00:00
z3d
65387def16 Light relief. 2011-01-14 05:51:02 +00:00
z3d
19f1f7c380 Console: Enhanced support for webkit/opera in light theme. 2011-01-14 04:45:59 +00:00
z3d
c36aaa62ba Readme (eng): decombobulation. 2011-01-13 22:34:10 +00:00
z3d
dc120847e1 Readme (en): Clarify "rejecting tunnels". 2011-01-13 22:16:43 +00:00
z3d
1aea5b3dec Additional light tweaks. 2011-01-13 21:39:04 +00:00
z3d
9ea41b6e67 More light tweaks. 2011-01-13 21:27:10 +00:00
z3d
4a85f30bf4 Light tweaks. 2011-01-13 20:58:12 +00:00
z3d
c4445143f9 merge of '6100fa1118decc83a309c2ccf8d128db2e9c2ef8'
and 'd804fb6b50abf7968a0198674912906c60ec9ff0'
2011-01-13 04:38:38 +00:00
z3d
9e2c063465 Console: tunnelmanager a:link color consistency fix. 2011-01-13 04:35:30 +00:00
dev
4dd78ed31b merge of '9d97a97ab57669b6ed2c246c966df9d4afcda899'
and 'bc18ab31728be1d004b18d113343c50f25f0a678'
2011-01-12 20:06:29 +00:00
dev
330f1f341e Fixes to Atom identification. 2011-01-12 20:06:22 +00:00
zzz
79bd5f1c11 fix log init problem 2011-01-12 13:28:32 +00:00
zzz
1ad1883d56 fix hashCode 2011-01-12 13:27:55 +00:00
z3d
4b85c56903 Console themes: fix news headings. 2011-01-12 12:48:16 +00:00
dev
7289c89171 merge of '52a34b607bb02c92ab1dac1ef16a3ce64462e39e'
and 'e6920b673f432050c4d56a74a2ff2074a2959e6a'
2011-01-11 17:51:46 +00:00
dev
c6a2e99a0d Added Intel Atom as (pentium3) as prescribed by the libgmp configure scripts. 2011-01-11 17:51:29 +00:00
dev
1757a2cc08 merge of '4e478ff8494e308808d6df2c47e368ac3aeb61aa'
and '51ae655150adb03f61e4ead408e1e7d827661dc7'
2011-01-11 16:40:37 +00:00
zzz
a51ae64e41 build tweak 2011-01-09 01:06:05 +00:00
zzz
fd4e4fbc64 * Data Structures: More caching improvements, don't cache where we shouldn't 2011-01-09 01:04:06 +00:00
zzz
9a63be8f69 * NetDB: Don't rescan netDb directory unless changed,
to reduce Hash cache thrash (backport from test4)
2011-01-09 01:03:05 +00:00
zzz
212c87ffd8 * DataHelper: Speed up and annotate sortStructures()
* RouterInfo:
      - Don't cache byteified data by default, to save ~1.5 MB
      - Don't create empty peers Set, to save ~100KB
2011-01-09 01:02:17 +00:00
dev
16509e5921 Better comments 2011-01-08 20:00:36 +00:00
dev
4c172760cc Corrected some identification code. 2011-01-08 19:58:04 +00:00
dev
7330e5fef8 Added support for new Intel family/model names.
Added proper support for using Core2 machines as P4.
Added support for identifying SSE 3/4.1/4.2/4A support on CPU.
2011-01-08 18:24:16 +00:00
zzz
6cfb2baad3 -9 2011-01-07 00:42:00 +00:00
zzz
3870924fbd * i2psnark: Improve request tracking to reduce memory usage 2011-01-07 00:23:25 +00:00
zzz
a692ab42fa add missing hashCode() 2011-01-06 15:54:54 +00:00
zzz
05a290cdd5 more caching 2011-01-06 15:54:39 +00:00
zzz
ea29c961ed log tweak 2011-01-05 21:01:03 +00:00
zzz
4005bd6804 reseed form button tweak 2011-01-05 20:34:56 +00:00
zzz
e826ce723a * i2psnark: Refactor request tracking to prevent possible deadlocks 2011-01-05 20:21:29 +00:00
zzz
6822bf7978 findbugs high-rank issues 2011-01-05 14:49:51 +00:00
zzz
e2c3ea3ffc log tweak thx ech 2011-01-05 14:47:48 +00:00
zzz
2e51577f39 fix up findbugs target 2011-01-04 22:35:34 +00:00
m1xxy
b92ba5edbb concretization in lang=es 2011-01-03 00:14:45 +00:00
m1xxy
aeb1d40658 minor tweaks and accomodation in lang=es 2011-01-03 00:07:05 +00:00
zzz
bb39d8c6fd disable spell check in textareas 2011-01-02 18:58:06 +00:00
zzz
bb74bc33d1 fix bw limits handling in standard session 2011-01-02 18:56:45 +00:00
zzz
af90121b47 cache tweak 2011-01-02 18:56:04 +00:00
zzz
f015ce1f0b log tweak 2011-01-02 18:55:26 +00:00
m1xxy
785d184676 corerection on eespite de 2011-01-02 06:32:42 +00:00
m1xxy
ca5ed9d1b7 merge of '36bd43007b45f4b59b1dc14a2cb02b06c9e7fa84'
and '82c6b46d2891bdaf3043f85ea25fd9f3bf5ab3e5'
2011-01-02 04:39:18 +00:00
m1xxy
8fdc4bc9b0 routerconsole de add ; 2011-01-02 04:36:00 +00:00
m1xxy
7d2bbaad94 actualizar -> actualización 2011-01-02 04:35:07 +00:00
zzz
ed8197f6d2 * Data Structures: More caching and cleanups 2010-12-31 13:21:05 +00:00
zzz
e0f77731c5 generics 2010-12-31 13:19:26 +00:00
zzz
3b51f420c4 better logging 2010-12-31 13:18:36 +00:00
zzz
cd1ed63908 javadoc 2010-12-31 13:18:17 +00:00
zzz
a64d0a54b1 * Datagram Dissector: Fix RuntimeException caused by reuse,
preventing iMule from connecting on UDP
                          (thanks devzero)
2010-12-31 13:16:46 +00:00
zzz
1b74b49e0f remove missing img 2010-12-31 13:16:14 +00:00
zzz
95cf306526 * i2psnark: Send cache directive for in-war icons 2010-12-31 13:14:57 +00:00
zzz
a18197dbdd - Add console request logging, enable with routerconsole.log=filename 2010-12-31 13:14:15 +00:00
zzz
dcb9d38114 - Make theme files and history.txt return 403 on error,
not 500, to avoid the new error page
2010-12-31 13:13:26 +00:00
zzz
544563672c - Link to full history.txt on help page 2010-12-31 13:12:40 +00:00
zzz
0de6c932f5 * OCMOSJ: Refactor cache keys for efficiency 2010-12-31 13:11:25 +00:00
z3d
ba8c8aa90d merge of '21a58b4579e454d8f04032726ab182a3176653da'
and 'a1a6a2d409864f97efb7af374431e7214c5a7976'
2010-12-31 07:16:08 +00:00
m1xxy
f9cc72e892 tweaks 2010-12-31 06:31:18 +00:00
m1xxy
751134f5df merge of '6ac923b4b6f858e909094ff3d0fbfbbfba7ff9d4'
and '8b279c27b4d263a1c9cc02ab7fe2e448e652f469'
2010-12-31 01:52:45 +00:00
m1xxy
4025a57529 grammar fix 2010-12-31 01:51:01 +00:00
m1xxy
bad27e648a fix typo 2010-12-31 01:49:03 +00:00
zzz
8ab1892560 history for prop, -5 2010-12-30 15:06:54 +00:00
zzz
6ec1772c82 propagate from branch 'i2p.i2p.zzz.test4' (head 544002db2f75a06bbd19571f24692055c41b3290)
to branch 'i2p.i2p' (head 18c56774615023acadd46474b890350cd02a08c9)
2010-12-30 15:01:53 +00:00
zzz
08a3165c44 * Data Structures:
- New SDSCache for SimpleDataStructures
      - New SimpleByteCache for byte[]
      - Cache Hash, PublicKey, and SigningPublicKey
      - Remove global lock in ByteCache
2010-12-30 15:01:39 +00:00
zzz
5d6edad9d4 * I2CP:
- Include the Hash in the DestReplyMessage on a failed lookup
        so the client may correlate replies
        (file omitted from previous checkin)
2010-12-30 13:18:22 +00:00
zzz
01f9be4622 propagate from branch 'i2p.i2p.zzz.test4' (head 764616dd0b3539990a05edb329ece0afd35261cb)
to branch 'i2p.i2p' (head 871752bfdd3d262d0fde193cf787e2705418936a)
2010-12-30 01:35:53 +00:00
zzz
5615b13027 Fix buttons on Firefox 4.0b 2010-12-30 01:35:13 +00:00
zzz
cc4158a7e1 * i2ptunnel:
- Use dropdown box to select interface for clients
      - Warn on index page if required fields not set
2010-12-30 00:36:41 +00:00
m1xxy
80ee0a3b54 merge of '4db34be5448beb1eab5ca54e2e417437a591d8e4'
and '6f964a29ceb436cab5b25b2a74cc225a8e53e88b'
2010-12-29 15:48:01 +00:00
m1xxy
f21b079e25 mods to pt 2010-12-29 15:42:39 +00:00
duck
8a4745a465 merge of 'af0d307e46e94ee1a32100b7ba28e243e8f82e74'
and 'e23be5b3f87b826c3e0d02aa479df283ad906489'
2010-12-29 14:19:47 +00:00
duck
7bd978e569 Fix typo 2010-12-29 14:15:33 +00:00
zzz
563e1f97e8 * DSAEngine: Restore variants of methods using a Hash argument,
required by Syndie, removed in 0.8.1
2010-12-29 14:07:13 +00:00
zzz
fc589db9b2 fix validation errors 2010-12-29 13:31:40 +00:00
zzz
3309b53401 fix validation errors 2010-12-29 13:12:35 +00:00
zzz
a61183303f add configreseed page 2010-12-29 12:56:48 +00:00
zzz
cd58dfdf99 add 500 error page 2010-12-29 12:36:03 +00:00
zzz
45f3a35fac - Add StartCom CA cert required for www.i2pbote.net 2010-12-29 12:35:24 +00:00
m1xxy
9919a41436 fix a typo spotted by user 2010-12-28 19:25:41 +00:00
m1xxy
42ea77df7f minor translation updates 2010-12-28 00:04:47 +00:00
zzz
ab4a5d15a1 history for prop, -2 2010-12-27 16:36:33 +00:00
zzz
f225c1cca0 propagate from branch 'i2p.i2p.zzz.test4' (head 56ba5c9f8d0779f91259df05b7be0826fe08cd84)
to branch 'i2p.i2p' (head 0ba2cc80363f5c7086bce7a43f43a9b095ed2d9e)
2010-12-27 16:21:09 +00:00
zzz
6ee162002a fix console jetty temp file names when in ssl-only mode 2010-12-27 15:56:19 +00:00
zzz
fefcb6c2cb prevent leak after exception 2010-12-26 23:35:27 +00:00
zzz
cdcbc80248 Addresses cleanup 2010-12-26 22:57:13 +00:00
sponge
965b2611b3 Evolve, document how the URI path fix works. Fix 302 redirects so they URL encode properly. bump to -1 2010-12-26 20:45:29 +00:00
zzz
443abce647 * I2CP:
- Move BWLimits and DestLookup message support from
        I2PSimpleSession to I2PSessionImpl
      - Include the Hash in the DestReplyMessage on a failed lookup
        so the client may correlate replies
      - Add support for parallel lookups and BWLimits requests
      - Add support for specifying the timeout for DestLookups
        (can only be smaller than the router timeout for now)
      - Extend dest lookup router timeout from 10s to 15s
2010-12-26 20:36:44 +00:00
sponge
923c3d8b4c Fix 302 redirect so that it encodes the URI path properly. 2010-12-26 18:45:13 +00:00
sponge
925f9d0a28 Add virgin ResourceHandler.java file 2010-12-26 18:13:14 +00:00
zzz
49b11bb49e refactor Addresses 2010-12-26 15:07:59 +00:00
zzz
5d494ba89a Move Addresses class from router to core so we can use it in i2ptunnel 2010-12-26 13:48:45 +00:00
zzz
cd0d062fca Fix last piece length calculation for torrents > 2GB (ticket #361) 2010-12-26 13:17:12 +00:00
zzz
b3d1a76146 Prep for caching by making SimpleDataStructures immutable after data has been set. 2010-12-26 13:04:52 +00:00
zzz
824d5a0d36 javadocs 2010-12-26 12:42:44 +00:00
zzz
34973371ac * Update:
- Change the UpdateHandler to try all sources in a loop, rather than one,
        so the user need not retry manually
      - For each source, fetch the first 56 bytes and check the version
        before downloading the whole thing, so we need not wait for every
        host to have the latest before updating the news.
2010-12-26 12:37:51 +00:00
zzz
7ee7cbf660 * Stats: Change stat.full default.to false (saves ~ 1MB) 2010-12-26 12:35:54 +00:00
zzz
66f3484508 * i2psnark: Backport TrackerClient NPE fix 2010-12-26 12:32:17 +00:00
zzz
c54b40288b * Addresses: Add listing capability for internal interfaces 2010-12-26 12:31:01 +00:00
zzz
ff0c168d65 * Certificate: Fix fatal null cert error 2010-12-26 12:29:55 +00:00
zzz
82e344055b * Certificate: Use a single static null cert in place of
tens of thousands of them
2010-12-24 17:39:31 +00:00
zzz
63c6613261 * configclients.jsp:
- Add form for I2CP options
      - Fix HTML errors
2010-12-24 16:52:23 +00:00
hiddenz
15a8d39ef5 router's index ru: multiple fixes
- translation fixes
- typo fixes
- grammar and spelling fixes
2010-12-23 20:05:33 +00:00
hiddenz
85629aca86 routerconsole: fix typo in russian translation 2010-12-23 20:02:10 +00:00
hiddenz
5069bebe99 merge of '28858996311a6bf5c6a1e8f6558502527f1ea9e9'
and 'f251674b3b5b8f06caee32cc5abca12103115022'
2010-12-23 18:50:32 +00:00
hiddenz
b81ff32434 routerconsole: small update of russian translation 2010-12-23 18:50:21 +00:00
hiddenz
5d2f5c7a1f merge of '04a2d141a4d20a86027b0345820c081a8460a671'
and '0c71002f6fde035669ce69ce9f263e9c231917f2'
2010-12-23 18:41:48 +00:00
hiddenz
b862d14ecb Sync russian translation of router's index page with english version 2010-12-23 18:37:58 +00:00
z3d
4e3effa7e5 merge of '878149500938c6886eb9e0274ba0901e8fe3a3bb'
and 'deab42b1e2bfe970ba51a868ab2b8c47181fdd15'
2010-12-22 00:03:56 +00:00
z3d
a825132961 Readme (eng): typo fixes. 2010-12-21 23:56:40 +00:00
z3d
bb637eb757 merge of 'be5741c3c94c1e0719f55180856bbdeecca4d5e2'
and 'cf23c2bccd1b205a714663148e4591cc09e9617c'
2010-12-21 10:21:37 +00:00
z3d
94f8b81bd3 TunnelManager css tweaks (light/dark/classic). 2010-12-21 10:20:27 +00:00
m1xxy
1d89e136bd translation: routerconsole es stub fixup 2010-12-19 21:59:07 +00:00
zzz
91f1ece753 adjust runner count based on max mem 2010-12-19 15:13:54 +00:00
m1xxy
6725ce096c routerconsole es stub 2010-12-19 12:02:43 +00:00
m1xxy
a568ad2bbc i2psnark es tweaks 2010-12-19 11:59:28 +00:00
z3d
8e72445273 merge of '2c3eb1b692122c7c96b2c547532274f1068fc7f5'
and 'ed99c2a20da18fdc068fa77418f54a1857152a16'
2010-12-19 09:10:49 +00:00
sponge
3c4994c0e1 Fix script so the proper encodeing is used in the JVM. 2010-12-19 00:40:01 +00:00
sponge
0802b9a8dc version bump, history.txt 2010-12-19 00:24:59 +00:00
sponge
ed5c61725a merge of 'daa35ac8b482063c4db4b6205ca5dacc045080a4'
and 'e19c106344aa97ad1765e79df75f96182f89d102'
2010-12-19 00:23:10 +00:00
sponge
4622080e07 Fix FileResource.java 2010-12-19 00:20:14 +00:00
sponge
8d6a12552c Fix URI.java, add FileResource.java 2010-12-19 00:19:26 +00:00
sponge
f8ed3c561e Add original URI.java source 2010-12-18 19:58:29 +00:00
zzz
7c8e5c6d66 retrofit SimpleDataStructure over SHA1Hash 2010-12-17 22:04:57 +00:00
zzz
d699eaaec9 change map class 2010-12-17 21:50:14 +00:00
zzz
60e57ec29e add some types 2010-12-17 21:49:34 +00:00
zzz
03f58d1886 shorten thread name 2010-12-17 21:48:04 +00:00
zzz
0bd75f0e56 comment out mains 2010-12-15 23:35:50 +00:00
zzz
df3fc6e05d Random cleanup 2010-12-15 23:19:34 +00:00
zzz
fe575a38aa fix up DH like YK 2010-12-15 22:59:35 +00:00
zzz
4c9558c586 adjust limits to reduce chance of running out; adjust limits based on max mem 2010-12-15 17:08:11 +00:00
zzz
2deee2b1b7 AES cleanups and javadoc 2010-12-15 16:10:03 +00:00
zzz
8e709eec2e fixup after prop 2010-12-15 15:19:09 +00:00
zzz
c7c7731f91 propagate from branch 'i2p.i2p' (head 3d405c867f6903bf1d69b04c1daebf3146882525)
to branch 'i2p.i2p.zzz.test4' (head bfd85b10fdd1542526a4b9c53e5d4a733087f317)
2010-12-15 15:09:48 +00:00
zzz
77f910ee36 add max conns to form 2010-12-15 13:41:11 +00:00
zzz
d000d2047d clean up jump host verification 2010-12-15 01:21:58 +00:00
zzz
9d41e86866 add jump list to form 2010-12-15 01:06:08 +00:00
zzz
c15c97f69c put blacklist mode on form 2010-12-14 22:14:29 +00:00
zzz
5ed8be2466 add conn limits to form 2010-12-14 21:39:29 +00:00
zzz
6826c1eb69 disable I2CP auth in-JVM 2010-12-14 20:30:00 +00:00
zzz
e772107c58 trivial cleanup 2010-12-14 14:34:50 +00:00
zzz
c44c222557 minor 2010-12-14 14:34:27 +00:00
zzz
8efefeeb5b * I2CP over SSL, enable with i2cp.SSL=true 2010-12-14 14:27:35 +00:00
zzz
59af763dcd do it the easy way 2010-12-13 15:28:06 +00:00
zzz
2880d61c1b * Pack200: Find and use either Oracle or Apache library at runtime;
neither required at compile time.
2010-12-13 14:01:46 +00:00
zzz
f194f78953 use base 64 for temp dir name 2010-12-12 22:09:04 +00:00
zzz
a5354f64a5 more classes pkg private 2010-12-12 22:07:26 +00:00
zzz
6d41aadc24 * I2CP:
- New option i2cp.disableInterface to turn off external I2CP port
        (7654) and allow internal clients only
      - Disallow internal connect when shut down
2010-12-12 22:06:30 +00:00
zzz
9a993c00e4 * graphs.jsp:
- Show selected refresh delay
      - Translate refresh delays
      - Fix setting delay to 'Never'
2010-12-12 22:04:06 +00:00
zzz
114c398056 shorten TrackerClient thread name 2010-12-12 21:45:32 +00:00
zzz
384f1bd174 update jetty.xml SSL comments 2010-12-12 21:32:00 +00:00
zzz
653a68b8a5 Disable I2CP host/port options when in router context 2010-12-12 21:30:29 +00:00
zzz
4a9f7b740c * Console:
- Add SSL support - To enable, change clients.config. Examples:
            ## Change to SSL only - just add a '-s'
            clientApp.0.args=-s 7657 ::1,127.0.0.1 ./webapps/
            ## Use both non-SSL and SSL - add '-s port interface'
            clientApp.0.args=7657 ::1,127.0.0.1 -s 7667 ::1,127.0.0.1 ./webapps/
            ## ...and change URLLauncher args further down for the browser to open https:// at startup if you like.
2010-12-05 19:04:33 +00:00
zzz
86de251691 fix QueuedI2CPMessageReader not stopping; javadocs 2010-12-04 22:27:24 +00:00
zzz
0b2bc726df fix SimpleSession NPE 2010-12-04 21:18:37 +00:00
zzz
b42967848e javadoc 2010-12-04 20:39:51 +00:00
zzz
04af255045 SimpleSession doesnt need a notifier thread 2010-12-04 20:39:40 +00:00
zzz
3d759d76cf javadoc, start notifier only after success 2010-12-04 20:39:22 +00:00
zzz
7c583fb1e6 convert mark router liveliness thread to SimpleScheduler 2010-12-04 20:34:57 +00:00
zzz
9aaf95ca98 * Threads:
- Reduce thread pool sizes based on memory and/or bandwidth limits
      - Tweak some thread names for clarity
2010-12-04 18:54:06 +00:00
zzz
6dfd9bca69 log tweaks 2010-12-04 18:48:01 +00:00
zzz
eadf472dd0 * I2PTunnel:
- For clients, use a common thread pool that expires idle threads
        rather than keeping 5 accept() threads for each client.
        This also removes the configurable (30s default) max wait time
        for a socket, this may have to be restored.
      - Use pool for HTTP decompression also.
2010-12-04 18:47:22 +00:00
zzz
04ea1fb9ca javadoc 2010-12-04 18:43:30 +00:00
zzz
947010ad01 I2PThread -> I2PAppThread 2010-12-04 18:42:40 +00:00
zzz
3a05abe556 add a stat to see if getBids() is taking too long 2010-12-04 18:41:12 +00:00
zzz
a1c69082e2 LBQ -> SynchronousQueue so it will expand the pool 2010-12-04 18:38:11 +00:00
zzz
467b082e82 * I2PTunnel:
- Limit server blockingHandle threads
      - Run standard server blockingHandles inline
2010-12-04 02:03:08 +00:00
zzz
5ab813179d dont update stats after failure 2010-12-03 21:30:32 +00:00
zzz
8976746867 mindless history.txt servlet 2010-12-03 20:40:34 +00:00
zzz
fabbda659b I2CP internal mode tweaks 2010-12-03 17:23:36 +00:00
zzz
e9e1890b14 * I2PTunnel:
- Extend header timeouts for HTTP and IRC server tunnels
2010-12-03 17:01:51 +00:00
zzz
5c73a60551 * I2PTunnel:
- Better logging of server errors
      - Return 503 to client before closing i2p socket if server is not there
2010-12-03 16:51:04 +00:00
zzz
ae6a6a1d9c * I2PTunnel: Get Log from the logManager instead of instantiating,
so we may adjust the levels on the fly
2010-12-03 15:20:00 +00:00
zzz
19c6760ea7 * I2CP: Change from the internal pseudo-socket that was
implemented in 0.7.9 to an internal Queue that directly
      passes I2CPMessage objects. For in-JVM clients,
      this eliminates two writer threads per client and
      avoids the serialization/deserialization of I2CP messages.
2010-12-01 18:57:05 +00:00
218 changed files with 15567 additions and 4139 deletions

View File

@@ -21,7 +21,7 @@ CWD=$(pwd)
TMP=/tmp
PKG=/$TMP/package-base-i2p
NAME=i2p-base
VERSION=0.0.3
VERSION=0.0.4
BUILD=1sponge
ARCH=noarch
INSTALL_DIR=opt

View File

@@ -3,7 +3,7 @@
i2p_start() {
# Check if router is up first!
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory status )" > /dev/null
/bin/su - -c "/bin/bash -l -c '( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\" ; directory status )'" > /dev/null
if [ $? -eq 0 ] ; then {
# I2p is already running, so tell the user.
echo "I2P is already running..."
@@ -14,13 +14,13 @@ i2p_start() {
# Just in-case there are leftover junk in /tmp...
rm -Rf `grep /tmp/hsperfdata_root/* -le i2p` /tmp/i2p-*.tmp /tmp/router.ping
# Now that all junk is cleaned up, start.
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory start )"
/bin/su - -c "/bin/bash -l -c '( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\" ; directory start )'"
}
fi
}
i2p_stop() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory stop )"
/bin/su - -c "/bin/bash -l -c '( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\" ; directory stop )'"
rm -Rf `grep /tmp/hsperfdata_root/* -le i2p` /tmp/i2p-*.tmp /tmp/router.ping
}
@@ -31,15 +31,15 @@ i2p_restart() {
}
i2p_status() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory status )"
/bin/su - -c "/bin/bash -l -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 )"
/bin/su - -c "/bin/bash -l -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 )"
/bin/su - -c "/bin/bash -l -c '( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\" ; directory dump )'"
}
case "$1" in

View File

@@ -137,7 +137,7 @@ public class ConnectionAcceptor implements Runnable
}
}
} else {
Thread t = new I2PAppThread(new Handler(socket), "Connection-" + socket);
Thread t = new I2PAppThread(new Handler(socket), "I2PSnark incoming connection");
t.start();
}
}

View File

@@ -14,11 +14,13 @@ import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
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.Base32;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
@@ -316,21 +318,44 @@ public class I2PSnarkUtil {
}
}
private static final int BASE32_HASH_LENGTH = 52; // 1 + Hash.HASH_LENGTH * 8 / 5
/** Base64 Hash or Hash.i2p or name.i2p using naming service */
Destination getDestination(String ip) {
if (ip == null) return null;
if (ip.endsWith(".i2p")) {
if (ip.length() < 520) { // key + ".i2p"
Destination dest = _context.namingService().lookup(ip);
if (dest != null)
return dest;
if (_manager != null && ip.length() == BASE32_HASH_LENGTH + 8 && ip.endsWith(".b32.i2p")) {
// Use existing I2PSession for b32 lookups if we have it
// This is much more efficient than using the naming service
I2PSession sess = _manager.getSession();
if (sess != null) {
byte[] b = Base32.decode(ip.substring(0, BASE32_HASH_LENGTH));
if (b != null) {
Hash h = new Hash(b);
if (_log.shouldLog(Log.INFO))
_log.info("Using existing session for lookup of " + ip);
try {
return sess.lookupDest(h);
} catch (I2PSessionException ise) {
}
}
}
}
if (_log.shouldLog(Log.INFO))
_log.info("Using naming service for lookup of " + ip);
return _context.namingService().lookup(ip);
}
if (_log.shouldLog(Log.INFO))
_log.info("Creating Destination for " + ip);
try {
return new Destination(ip.substring(0, ip.length()-4)); // sans .i2p
} catch (DataFormatException dfe) {
return null;
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Creating Destination for " + ip);
try {
return new Destination(ip);
} catch (DataFormatException dfe) {

View File

@@ -39,7 +39,13 @@ class Message
final static byte REQUEST = 6;
final static byte PIECE = 7;
final static byte CANCEL = 8;
final static byte EXTENSION = 20;
final static byte PORT = 9; // DHT (BEP 5)
final static byte SUGGEST = 13; // Fast (BEP 6)
final static byte HAVE_ALL = 14; // Fast (BEP 6)
final static byte HAVE_NONE = 15; // Fast (BEP 6)
final static byte REJECT = 16; // Fast (BEP 6)
final static byte ALLOWED_FAST = 17; // Fast (BEP 6)
final static byte EXTENSION = 20; // BEP 10
// Not all fields are used for every message.
// KEEP_ALIVE doesn't have a real wire representation

View File

@@ -291,7 +291,7 @@ public class MetaInfo
if (piece >= 0 && piece < pieces -1)
return piece_length;
else if (piece == pieces -1)
return (int)(length - piece * piece_length);
return (int)(length - ((long)piece * piece_length));
else
throw new IndexOutOfBoundsException("no piece: " + piece);
}

View File

@@ -63,6 +63,7 @@ public class Peer implements Comparable
// bytes per bt spec: 0011223344556677
static final long OPTION_EXTENSION = 0x0000000000100000l;
static final long OPTION_FAST = 0x0000000000000004l;
static final long OPTION_DHT = 0x0000000000000001l;
private long options;
/**
@@ -77,7 +78,7 @@ public class Peer implements Comparable
this.my_id = my_id;
this.metainfo = metainfo;
_id = ++__id;
//_log.debug("Creating a new peer with " + peerID.getAddress().calculateHash().toBase64(), new Exception("creating"));
//_log.debug("Creating a new peer with " + peerID.toString(), new Exception("creating"));
}
/**
@@ -101,7 +102,7 @@ public class Peer implements Comparable
this.peerID = new PeerID(id, sock.getPeerDestination());
_id = ++__id;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating a new peer with " + peerID.getAddress().calculateHash().toBase64(), new Exception("creating " + _id));
_log.debug("Creating a new peer with " + peerID.toString(), new Exception("creating " + _id));
}
/**
@@ -197,7 +198,7 @@ public class Peer implements Comparable
throw new IllegalStateException("Peer already started");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Running connection to " + peerID.getAddress().calculateHash().toBase64(), new Exception("connecting"));
_log.debug("Running connection to " + peerID.toString(), new Exception("connecting"));
try
{
// Do we need to handshake?
@@ -430,6 +431,7 @@ public class Peer implements Comparable
/**
* Are we currently requesting the piece?
* @deprecated deadlocks
* @since 0.8.1
*/
boolean isRequesting(int p) {

View File

@@ -428,7 +428,7 @@ public class PeerCoordinator implements PeerListener
peer.runConnection(_util, listener, bitfield);
}
};
String threadName = peer.toString();
String threadName = "Snark peer " + peer.toString();
new I2PAppThread(r, threadName).start();
return true;
}
@@ -591,10 +591,7 @@ public class PeerCoordinator implements PeerListener
}
if (piece == null)
wantedSize = wantedPieces.size();
} // synch
// Don't sync the following, deadlock from calling each Peer's isRequesting()
//Only request a piece we've requested before if there's no other choice.
if (piece == null) {
// AND if there are almost no wanted pieces left (real end game).
@@ -612,22 +609,12 @@ public class PeerCoordinator implements PeerListener
Piece p = it2.next();
if (havePieces.get(p.getId())) {
// limit number of parallel requests
int requestedCount = 0;
for (Peer pr : peers) {
// deadlock if synced on wantedPieces
if (pr.isRequesting(p.getId())) {
if (pr.equals(peer)) {
// don't give it to him again
requestedCount = MAX_PARALLEL_REQUESTS;
break;
}
if (++requestedCount >= MAX_PARALLEL_REQUESTS)
break;
}
}
if (requestedCount >= MAX_PARALLEL_REQUESTS)
continue;
piece = p;
int requestedCount = p.getRequestCount();
if (requestedCount < MAX_PARALLEL_REQUESTS &&
!p.isRequestedBy(peer)) {
piece = p;
break;
}
}
}
if (piece == null) {
@@ -648,9 +635,10 @@ public class PeerCoordinator implements PeerListener
if (record) {
if (_log.shouldLog(Log.INFO))
_log.info(peer + " is now requesting: piece " + piece + " priority " + piece.getPriority());
piece.setRequested(true);
piece.setRequested(peer, true);
}
return piece.getId();
} // synch
}
/**
@@ -948,7 +936,7 @@ public class PeerCoordinator implements PeerListener
}
} // else drop the empty partial piece
// synchs on wantedPieces...
markUnrequestedIfOnlyOne(peer, pp.getPiece());
markUnrequested(peer, pp.getPiece());
}
if (_log.shouldLog(Log.INFO))
_log.info("Partial list size now: " + partialPieces.size());
@@ -974,7 +962,7 @@ public class PeerCoordinator implements PeerListener
// this is just a double-check, it should be in there
for(Piece piece : wantedPieces) {
if (piece.getId() == savedPiece) {
piece.setRequested(true);
piece.setRequested(peer, true);
if (_log.shouldLog(Log.INFO)) {
_log.info("Restoring orphaned partial piece " + pp +
" Partial list size now: " + partialPieces.size());
@@ -1053,33 +1041,16 @@ public class PeerCoordinator implements PeerListener
}
}
/** Clear the requested flag for a piece if the peer
** is the only one requesting it
/**
* Clear the requested flag for a piece
*/
private void markUnrequestedIfOnlyOne(Peer peer, int piece)
private void markUnrequested(Peer peer, int piece)
{
// see if anybody else is requesting
for (Peer p : peers) {
if (p.equals(peer))
continue;
if (p.state == null)
continue;
// FIXME don't go into the state
if (p.state.getRequestedPieces().contains(Integer.valueOf(piece))) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Another peer is requesting piece " + piece);
return;
}
}
// nobody is, so mark unrequested
synchronized(wantedPieces)
{
for (Piece pc : wantedPieces) {
if (pc.getId() == piece) {
pc.setRequested(false);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Removing from request list piece " + piece);
pc.setRequested(peer, false);
return;
}
}

View File

@@ -464,7 +464,7 @@ class PeerState implements DataLoader
/**
* @return all pieces we are currently requesting, or empty Set
*/
synchronized Set<Integer> getRequestedPieces() {
synchronized private Set<Integer> getRequestedPieces() {
Set<Integer> rv = new HashSet(outstandingRequests.size() + 1);
for (Request req : outstandingRequests) {
rv.add(Integer.valueOf(req.piece));
@@ -564,6 +564,7 @@ class PeerState implements DataLoader
/**
* Are we currently requesting the piece?
* @deprecated deadlocks
* @since 0.8.1
*/
synchronized boolean isRequesting(int piece) {

View File

@@ -1,24 +1,25 @@
package org.klomp.snark;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import net.i2p.util.ConcurrentHashSet;
/**
* This class is used solely by PeerCoordinator.
* Caller must synchronize on many of these methods.
*/
class Piece implements Comparable {
private int id;
private Set<PeerID> peers;
private boolean requested;
private final int id;
private final Set<PeerID> peers;
/** @since 0.8.3 */
private Set<PeerID> requests;
/** @since 0.8.1 */
private int priority;
public Piece(int id) {
this.id = id;
this.peers = new ConcurrentHashSet();
this.peers = new HashSet(I2PSnarkUtil.MAX_CONNECTIONS);
// defer creating requests to save memory
}
/**
@@ -49,12 +50,51 @@ class Piece implements Comparable {
}
public int getId() { return this.id; }
/** @deprecated unused */
public Set<PeerID> getPeers() { return this.peers; }
/** caller must synchronize */
public boolean addPeer(Peer peer) { return this.peers.add(peer.getPeerID()); }
/** caller must synchronize */
public boolean removePeer(Peer peer) { return this.peers.remove(peer.getPeerID()); }
public boolean isRequested() { return this.requested; }
public void setRequested(boolean requested) { this.requested = requested; }
/** caller must synchronize */
public boolean isRequested() {
return this.requests != null && !this.requests.isEmpty();
}
/**
* Since 0.8.3, keep track of who is requesting here,
* to avoid deadlocks from querying each peer.
* Caller must synchronize
*/
public void setRequested(Peer peer, boolean requested) {
if (requested) {
if (this.requests == null)
this.requests = new HashSet(2);
this.requests.add(peer.getPeerID());
} else {
if (this.requests != null)
this.requests.remove(peer.getPeerID());
}
}
/**
* Is peer requesting this piece?
* Caller must synchronize
* @since 0.8.3
*/
public boolean isRequestedBy(Peer peer) {
return this.requests != null && this.requests.contains(peer.getPeerID());
}
/**
* How many peers are requesting this piece?
* Caller must synchronize
* @since 0.8.3
*/
public int getRequestCount() {
return this.requests == null ? 0 : this.requests.size();
}
/** @return default 0 @since 0.8.1 */
public int getPriority() { return this.priority; }

View File

@@ -72,8 +72,10 @@ public class TrackerClient extends I2PAppThread
public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator)
{
super();
// Set unique name.
super("TrackerClient-" + urlencode(coordinator.getID()));
String id = urlencode(coordinator.getID());
setName("TrackerClient " + id.substring(id.length() - 12));
_util = util;
this.meta = meta;
this.coordinator = coordinator;
@@ -274,7 +276,7 @@ public class TrackerClient extends I2PAppThread
// only delay if we actually make an attempt to add peer
if(coordinator.addPeer(cur)) {
int delay = DELAY_MUL;
delay *= ((int)cur.getPeerID().getAddress().calculateHash().toBase64().charAt(0)) % 10;
delay *= r.nextInt(10);
delay += DELAY_MIN;
sleptTime += delay;
try { Thread.sleep(delay); } catch (InterruptedException ie) {}

View File

@@ -157,7 +157,7 @@ public class BEValue
* values. This operation only succeeds when the BEValue is actually
* a Map, otherwise it will throw a InvalidBEncodingException.
*/
public Map<BEValue, BEValue> getMap() throws InvalidBEncodingException
public Map<String, BEValue> getMap() throws InvalidBEncodingException
{
try
{

View File

@@ -99,6 +99,17 @@ public class I2PSnarkServlet extends Default {
return _resourceBase.addPath(pathInContext);
}
/**
* Tell the browser to cache the icons
* @since 0.8.3
*/
@Override
public void handleGet(HttpServletRequest request, HttpServletResponse response, String pathInContext, Resource resource, boolean endsWithSlash) throws ServletException, IOException {
if (resource.getName().startsWith("jar:file:"))
response.setHeader("Cache-Control", "max-age=86400"); // cache for a day
super.handleGet(request, response, pathInContext, resource, endsWithSlash);
}
/**
* Some parts modified from:
* <pre>
@@ -329,14 +340,18 @@ public class I2PSnarkServlet extends Default {
// Opera and text-mode browsers: no &thinsp; and no input type=image values submitted
String ua = req.getHeader("User-Agent");
boolean isDegraded = ua != null && (ua.startsWith("Opera") || ua.startsWith("Lynx") ||
boolean isDegraded = ua != null && (ua.startsWith("Lynx") ||
ua.startsWith("ELinks") || ua.startsWith("Dillo"));
boolean noThinsp = isDegraded || ua.startsWith("Opera");
if (_manager.util().connected()) {
if (isDegraded)
out.write("<a href=\"/i2psnark/?action=StopAll&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"StopAll\" title=\"");
else {
// http://www.onenaught.com/posts/382/firefox-4-change-input-type-image-only-submits-x-and-y-not-name
//out.write("<input type=\"image\" name=\"action\" value=\"StopAll\" title=\"");
out.write("<input type=\"image\" name=\"action_StopAll\" value=\"foo\" title=\"");
}
out.write(_("Stop all torrents and the I2P tunnel"));
out.write("\" src=\"" + _imgPath + "stop_all.png\" alt=\"");
out.write(_("Stop All"));
@@ -347,7 +362,7 @@ public class I2PSnarkServlet extends Default {
if (isDegraded)
out.write("<a href=\"/i2psnark/?action=StartAll&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"StartAll\" title=\"");
out.write("<input type=\"image\" name=\"action_StartAll\" value=\"foo\" title=\"");
out.write(_("Start all torrents and the I2P tunnel"));
out.write("\" src=\"" + _imgPath + "start_all.png\" alt=\"");
out.write(_("Start All"));
@@ -362,7 +377,7 @@ public class I2PSnarkServlet extends Default {
Snark snark = (Snark)snarks.get(i);
boolean showDebug = "2".equals(peerParam);
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam);
displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, showDebug);
displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, noThinsp, showDebug);
}
if (snarks.isEmpty()) {
@@ -404,8 +419,19 @@ public class I2PSnarkServlet extends Default {
private void processRequest(HttpServletRequest req) {
String action = req.getParameter("action");
if (action == null) {
_manager.addMessage("No action specified");
return;
// http://www.onenaught.com/posts/382/firefox-4-change-input-type-image-only-submits-x-and-y-not-name
Map params = req.getParameterMap();
for (Object o : params.keySet()) {
String key = (String) o;
if (key.startsWith("action_") && key.endsWith(".x")) {
action = key.substring(0, key.length() - 2).substring(7);
break;
}
}
if (action == null) {
_manager.addMessage("No action specified");
return;
}
}
// sadly, Opera doesn't send value with input type=image, so we have to use GET there
//if (!"POST".equals(req.getMethod())) {
@@ -698,7 +724,7 @@ public class I2PSnarkServlet extends Default {
private static final int MAX_DISPLAYED_FILENAME_LENGTH = 50;
private static final int MAX_DISPLAYED_ERROR_LENGTH = 43;
private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers,
boolean isDegraded, boolean showDebug) throws IOException {
boolean isDegraded, boolean noThinsp, boolean showDebug) throws IOException {
String filename = snark.torrent;
File f = new File(filename);
filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name
@@ -758,11 +784,11 @@ public class I2PSnarkServlet extends Default {
if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
curPeers + thinsp(isDegraded) +
curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
": " + curPeers + thinsp(isDegraded) +
": " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
else {
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
@@ -774,11 +800,11 @@ public class I2PSnarkServlet extends Default {
if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
curPeers + thinsp(isDegraded) +
curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
": " + curPeers + thinsp(isDegraded) +
": " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
else
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "complete.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Complete");
@@ -786,24 +812,24 @@ public class I2PSnarkServlet extends Default {
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
curPeers + thinsp(isDegraded) +
curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning && curPeers > 0 && downBps > 0)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
": " + curPeers + thinsp(isDegraded) +
": " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
else if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
curPeers + thinsp(isDegraded) +
curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning && curPeers > 0)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
": " + curPeers + thinsp(isDegraded) +
": " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
else if (isRunning && knownPeers > 0)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers") +
": 0" + thinsp(isDegraded) + knownPeers ;
": 0" + thinsp(noThinsp) + knownPeers ;
else if (isRunning)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers");
else
@@ -880,7 +906,7 @@ public class I2PSnarkServlet extends Default {
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentDownloaded " + rowClass + "\">");
if (remaining > 0)
out.write(formatSize(total-remaining) + thinsp(isDegraded) + formatSize(total));
out.write(formatSize(total-remaining) + thinsp(noThinsp) + formatSize(total));
else
out.write(formatSize(total)); // 3GB
out.write("</td>\n\t");
@@ -905,7 +931,7 @@ public class I2PSnarkServlet extends Default {
if (isDegraded)
out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"Stop_" + b64 + "\" title=\"");
out.write("<input type=\"image\" name=\"action_Stop_" + b64 + "\" value=\"foo\" title=\"");
out.write(_("Stop the torrent"));
out.write("\" src=\"" + _imgPath + "stop.png\" alt=\"");
out.write(_("Stop"));
@@ -917,7 +943,7 @@ public class I2PSnarkServlet extends Default {
if (isDegraded)
out.write("<a href=\"/i2psnark/?action=Start_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"Start_" + b64 + "\" title=\"");
out.write("<input type=\"image\" name=\"action_Start_" + b64 + "\" value=\"foo\" title=\"");
out.write(_("Start the torrent"));
out.write("\" src=\"" + _imgPath + "start.png\" alt=\"");
out.write(_("Start"));
@@ -929,7 +955,7 @@ public class I2PSnarkServlet extends Default {
if (isDegraded)
out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"Remove_" + b64 + "\" title=\"");
out.write("<input type=\"image\" name=\"action_Remove_" + b64 + "\" value=\"foo\" title=\"");
out.write(_("Remove the torrent from the active list, deleting the .torrent file"));
out.write("\" onclick=\"if (!confirm('");
// Can't figure out how to escape double quotes inside the onclick string.
@@ -946,7 +972,7 @@ public class I2PSnarkServlet extends Default {
if (isDegraded)
out.write("<a href=\"/i2psnark/?action=Delete_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"Delete_" + b64 + "\" title=\"");
out.write("<input type=\"image\" name=\"action_Delete_" + b64 + "\" value=\"foo\" title=\"");
out.write(_("Delete the .torrent file and the associated data file(s)"));
out.write("\" onclick=\"if (!confirm('");
// Can't figure out how to escape double quotes inside the onclick string.
@@ -1384,7 +1410,7 @@ public class I2PSnarkServlet extends Default {
private static String urlify(String s) {
StringBuilder buf = new StringBuilder(256);
// browsers seem to work without doing this but let's be strict
String link = s.replace("&", "&amp;");
String link = s.replace("&", "&amp;").replace(" ", "%20");
buf.append("<a href=\"").append(link).append("\">").append(link).append("</a>");
return buf.toString();
}

View File

@@ -9,7 +9,7 @@ msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-12-19 03:16+0000\n"
"PO-Revision-Date: 2010-12-19 04:49+0100\n"
"PO-Revision-Date: 2011-01-03 00:58+0100\n"
"Last-Translator: mixxy <m1xxy@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
@@ -269,7 +269,7 @@ msgstr "Tiempo restante para completar la descarga"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:293
msgid "ETA"
msgstr "Completado&nbsp;en"
msgstr "Tiempo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "Downloaded"
@@ -323,7 +323,7 @@ msgstr "Arrancar todos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:372
msgid "No torrents loaded."
msgstr "No cargado ningún torrent"
msgstr "No está cargado ningún torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
msgid "Totals"
@@ -453,7 +453,7 @@ msgstr "completo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:792
msgid "OK"
msgstr "Bien"
msgstr "bien"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801
@@ -644,7 +644,7 @@ msgstr "Si marcado, los torrents añadidos se iniciarán de forma automática."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1198
msgid "Theme"
msgstr "tema"
msgstr "Tema"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1211
msgid "Startup delay"
@@ -664,7 +664,7 @@ msgstr "pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244
msgid "Up bandwidth limit"
msgstr "Límite de ancho de banda para la subida"
msgstr "Límite del ancho de banda para la subida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247
msgid "Half available bandwidth recommended."
@@ -696,7 +696,7 @@ msgstr "Preferencias de salida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286
msgid "I2CP host"
msgstr "Huésped I2CP"
msgstr "Anfitrión I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
msgid "I2CP port"

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-12-17 15:04+0000\n"
"POT-Creation-Date: 2011-01-20 19:26+0000\n"
"PO-Revision-Date: 2010-06-15 09:07+0100\n"
"Last-Translator: duck <duck@mail.i2p>\n"
"Language-Team: duck <duck@mail.i2p>, monkeybrains <monkeybrains@mail.i2p>\n"
@@ -104,7 +104,8 @@ msgstr "Open Tracker lijst gewijzigd - torrent herstart nodig."
#: ../java/src/org/klomp/snark/SnarkManager.java:438
#, java-format
msgid "{0} theme loaded, return to main i2psnark page to view."
msgstr "{0} thema geladen, ga naar de hoofd i2psnark pagina om deze te bekijken."
msgstr ""
"{0} thema geladen, ga naar de hoofd i2psnark pagina om deze te bekijken."
#: ../java/src/org/klomp/snark/SnarkManager.java:445
msgid "Configuration unchanged."
@@ -234,176 +235,176 @@ msgstr "Kan niet verbinden met I2P!"
msgid "Unable to add {0}"
msgstr "Kan {0} niet toevoegen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:185
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:196
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - Anonieme BitTorrent Client"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:198
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:209
msgid "Torrents"
msgstr "Torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:201
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:208
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:212
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:219
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1003
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:205
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:216
msgid "Refresh page"
msgstr "Ververs pagina"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:210
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:221
msgid "Forum"
msgstr "Forum"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:264
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1483
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1509
msgid "Status"
msgstr "Status"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:272
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:281
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:283
msgid "Hide Peers"
msgstr "Verberg Peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:279
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:290
msgid "Show Peers"
msgstr "Toon Peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:286
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490
msgid "Torrent"
msgstr "Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:290
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:301
msgid "Estimated time remaining"
msgstr "Schatting resterende tijd"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:293
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:304
msgid "ETA"
msgstr "ETA"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308
msgid "Downloaded"
msgstr "Gedownload"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:300
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:314
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:311
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:325
msgid "RX"
msgstr "RX"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:304
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315
msgid "Uploaded"
msgstr "Geupload"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:307
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:318
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:335
msgid "TX"
msgstr "TX"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:312
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:323
msgid "Down Rate"
msgstr "Down Snelheid"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:317
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:326
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:337
msgid "Rate"
msgstr "Rato"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:322
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:333
msgid "Up Rate"
msgstr "Up Snelheid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:340
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:355
msgid "Stop all torrents and the I2P tunnel"
msgstr "Stop alle torrents en de I2P tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:357
msgid "Stop All"
msgstr "Stop Alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:351
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:366
msgid "Start all torrents and the I2P tunnel"
msgstr "Start alle torrents en de I2P tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:368
msgid "Start All"
msgstr "Start Alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:372
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:387
msgid "No torrents loaded."
msgstr "Geen torrents geladen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:392
msgid "Totals"
msgstr "Totalen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:379
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:394
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "1 torrent"
msgstr[1] "{0} torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:382
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:397
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "1 verbonden peer"
msgstr[1] "{0} verbonden peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:454
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:480
#, java-format
msgid "Fetching {0}"
msgstr "Downloaden {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:484
msgid "Invalid URL - must start with http://"
msgstr "Ongeldige URL - moet beginnen met http://"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:489
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515
#, java-format
msgid "Starting up torrent {0}"
msgstr "Starten met torrent {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:527
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:553
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Torrent bestand verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:533
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:543
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:559
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:569
#, java-format
msgid "Data file deleted: {0}"
msgstr "Data bestand verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:545
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Kan data bestand niet verwijderen: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:580
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Data directory verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:587
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:613
msgid "Error creating torrent - you must select a tracker"
msgstr "Fout bij maken van torrent - je moet een tracker selecteren"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:602
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:628
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Torrent gemaakt voor \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:605
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631
#, java-format
msgid ""
"Many I2P trackers require you to register new torrents before seeding - "
@@ -412,121 +413,121 @@ msgstr ""
"Veel I2P trackers vereisen dat je de nieuwe torrent registreert voor het "
"seeden - doe dit voordat je \"{0}\" start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:607
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Fout bij het maken van een torrent voor \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:610
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:636
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Kan geen torrent maken voor niet-bestaande data: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:613
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:639
msgid "Error creating torrent - you must enter a file or directory"
msgstr ""
"Fout bij het maken van de torrent - je moet een bestand of directory invullen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:616
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:642
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Stoppen van alle torrents en sluiten van I2P tunnel."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:627
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:653
msgid "I2P tunnel closed."
msgstr "I2P tunnel gesloten."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:630
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:656
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Openen van de I2P tunnel en starten van alle torrents."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:759
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:764
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:770
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:790
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
msgid "Tracker Error"
msgstr "Tracker Fout"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:762
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:766
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:778
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:782
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:790
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:794
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:799
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:803
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:788
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:792
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:804
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:816
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "1 peer"
msgstr[1] "{0} peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:775
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:780
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:806
msgid "Seeding"
msgstr "Seeding"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:784
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1533
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559
msgid "Complete"
msgstr "Voltooid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:792
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:813
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:818
msgid "OK"
msgstr "OK"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:822
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:827
msgid "Stalled"
msgstr "Vastgelopen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:831
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:834
msgid "No Peers"
msgstr "Geen Peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
msgid "Stopped"
msgstr "Gestopt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863
#, java-format
msgid "Details at {0} tracker"
msgstr "Details op de {0} tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:838
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:864
msgid "Info"
msgstr "Info"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:853
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:879
msgid "View files"
msgstr "Bekijk bestanden"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:855
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:881
msgid "Open file"
msgstr "Open bestand"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:865
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:891
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1595
msgid "Open"
msgstr "Open"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:909
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:935
msgid "Stop the torrent"
msgstr "Stop de torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:911
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:937
msgid "Stop"
msgstr "Stop"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:921
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:947
msgid "Start the torrent"
msgstr "Start de torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:923
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:949
msgid "Start"
msgstr "Start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:959
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr ""
"Verwijder de torrent van de actieve lijst, het .torrent bestand wordt "
@@ -535,7 +536,7 @@ msgstr ""
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:938
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:964
#, java-format
msgid ""
"Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded "
@@ -544,18 +545,18 @@ msgstr ""
"Weet je zeker dat je het bestand \\''{0}.torrent\\'' wilt verwijderen "
"(gedownloade data zal niet worden verwijderd) ?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:941
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:967
msgid "Remove"
msgstr "Weghalen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:950
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:976
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Verwijder het .torrent bestand en de gerelateerde data bestand(en)"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:981
#, java-format
msgid ""
"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded "
@@ -564,151 +565,151 @@ msgstr ""
"Weet je zeker dat je de torrent \\''{0}\\'' en alle gedownloade data wilt "
"verwijderen?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:984
msgid "Delete"
msgstr "Verwijderen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:991
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017
msgid "Unknown"
msgstr "Onbekend"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1027
msgid "Seed"
msgstr "Seed"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1019
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1045
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "Niet interessant (De peer heeft geen stukken die we nodig hebben)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1021
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1047
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "Verstikt (De peer laat ons niet toe om stukken op te vragen)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1035
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "Niet geïnteresseerd (We heben geen stukken die de peer nodig heeft)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1037
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Verstikt (We laten de peer niet toe om stukken op te vragen)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1092
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1118
msgid "Add Torrent"
msgstr "Torrent Toevoegen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1120
msgid "From URL"
msgstr "Van URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1097
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1123
msgid "Torrent file must originate from an I2P-based tracker"
msgstr "Torrent bestand moet vaan een I2P tracker komen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1102
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1128
msgid "Add torrent"
msgstr "Torrent toevoegen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1131
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr "Je kan ook .torrent bestanden kopieren naar: {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1107
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1133
msgid "Removing a .torrent will cause it to stop."
msgstr "Verwijderen van een .torrent zorgt dat deze stopt."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1131
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1157
msgid "Create Torrent"
msgstr "Creëer Torrent"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1134
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1160
msgid "Data to seed"
msgstr "Data om te seeden"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1138
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164
msgid "File or directory to seed (must be within the specified path)"
msgstr ""
"Bestand of directory om te seeden (moet binnen het gespecificeerde pad zijn)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1140
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1166
msgid "Tracker"
msgstr "Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1142
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1168
msgid "Select a tracker"
msgstr "Selecteer een tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1155
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1181
msgid "or"
msgstr "of"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1158
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1184
msgid "Specify custom tracker announce URL"
msgstr "Specificeer aangepaste tracker aankondigings URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1161
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1187
msgid "Create torrent"
msgstr "Creëer torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1180
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1317
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1343
msgid "Configuration"
msgstr "Configuratie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1184
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210
msgid "Data directory"
msgstr "Data directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1186
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1212
msgid "Edit i2psnark.config and restart to change"
msgstr "Bewerk i2psnark.config en herstart de wijziging"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216
msgid "Auto start"
msgstr "Auto start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1194
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1220
msgid "If checked, automatically start torrents that are added"
msgstr "Indien aangevinkt, start toegevoegde torrents automatisch"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1198
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224
msgid "Theme"
msgstr "Thema"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1211
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
msgid "Startup delay"
msgstr "Startup vertraging"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1213
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1239
msgid "minutes"
msgstr "minuten"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263
msgid "Total uploader limit"
msgstr "Totale uploader limiet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1266
msgid "peers"
msgstr "peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270
msgid "Up bandwidth limit"
msgstr "Up bandbreedte limiet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273
msgid "Half available bandwidth recommended."
msgstr "Helft van beschikbare bandbreedte aanbevolen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1249
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275
msgid "View or change router bandwidth"
msgstr "Bekijk of wijzig router bandbreedte"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279
msgid "Use open trackers also"
msgstr "Gebruik ook open trackers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1257
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283
msgid ""
"If checked, announce torrents to open trackers as well as the tracker listed "
"in the torrent file"
@@ -716,123 +717,123 @@ msgstr ""
"Indien aangevinkt, kondig torrents ook aan bij de tracker uit het torrent "
"bestand"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287
msgid "Open tracker announce URLs"
msgstr "Open tracker aankondigings URLs"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1299
msgid "Inbound Settings"
msgstr "Inkomende Instellingen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305
msgid "Outbound Settings"
msgstr "Uitgaande Instellingen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1312
msgid "I2CP host"
msgstr "I2CP host"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1317
msgid "I2CP port"
msgstr "I2CP poort"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1303
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329
msgid "I2CP options"
msgstr "I2CP opties"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1308
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1334
msgid "Save configuration"
msgstr "Configuratie opslaan"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1325
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1351
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "1 hop"
msgstr[1] "{0} hops"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1326
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1352
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "1 tunnel"
msgstr[1] "{0} tunnels"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1480
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1506
msgid "Size"
msgstr "Grootte"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1487
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1513
msgid "Priority"
msgstr "Prioriteit"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1492
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518
msgid "Up to higher level directory"
msgstr "Naar bovenliggende directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1543
msgid "Directory"
msgstr "Directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1522
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1548
msgid "Torrent not found?"
msgstr "Torrent niet gevonden?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556
msgid "File not found in torrent?"
msgstr "Bestand niet gevonden in torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1543
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569
msgid "complete"
msgstr "voltooid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1570
msgid "bytes remaining"
msgstr "bytes resterend"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1595
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1621
msgid "High"
msgstr "Hoog"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1600
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1626
msgid "Normal"
msgstr "Normaal"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1605
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1631
msgid "Skip"
msgstr "Overslaan"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1614
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1640
msgid "Save priorities"
msgstr "Prioriteiten opslaan"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1752
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent gedownload van {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1746
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1772
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent draait al: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1748
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1774
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent zit al in de wachtrij: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1755
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1781
#, java-format
msgid "Failed to copy torrent file to {0}"
msgstr "Kan het torrent bestand niet kopieren naar {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1759
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1785
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Torrent op {0} was niet geldig"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1764
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1790
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Torrent was niet ontvangen van {0}"

View File

@@ -9,7 +9,7 @@ msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-12-19 03:16+0000\n"
"PO-Revision-Date: 2010-12-19 04:48+0100\n"
"PO-Revision-Date: 2010-12-31 01:09+0100\n"
"Last-Translator: mixxy <m1xxy@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
@@ -118,12 +118,12 @@ msgstr "Conectando com I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:497
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Error ao se conectar com I2P - Verifique a sua configuração I2CP!"
msgstr "Erro ao se conectar com I2P - Verifique a sua configuração I2CP!"
#: ../java/src/org/klomp/snark/SnarkManager.java:506
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Error: Não se pode adicionar o torrent {0}."
msgstr "Erro: Não se pode adicionar o torrent {0}."
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:528
@@ -194,7 +194,7 @@ msgstr "Torrents maiores que \"{0}\" Bytes ainda não funcionam, se apagará \"{
#: ../java/src/org/klomp/snark/SnarkManager.java:767
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Error: Não se pode quitar o torrent \"{0}\"."
msgstr "Erro: Não se pode quitar o torrent \"{0}\"."
#: ../java/src/org/klomp/snark/SnarkManager.java:794
#, java-format
@@ -269,7 +269,7 @@ msgstr "Tempo que falta para completar"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:293
msgid "ETA"
msgstr "Completado&nbsp;em"
msgstr "Tempo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "Downloaded"
@@ -299,7 +299,7 @@ msgstr "Taça de descarga"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:317
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:326
msgid "Rate"
msgstr "Tasa"
msgstr "Taça"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:322
msgid "Up Rate"
@@ -382,7 +382,7 @@ msgstr "Apagada a pasta de dados: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:587
msgid "Error creating torrent - you must select a tracker"
msgstr "Error ao criar o torrent - Tens que elegir um rastreador."
msgstr "Erro ao criar o torrent - Tens que elegir um rastreador."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:602
#, java-format
@@ -392,12 +392,12 @@ msgstr "Torrent criado para \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:605
#, java-format
msgid "Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\""
msgstr "Muitos rastreadores no I2P exigem que você registre novos torrents antes de poder sembrá-los. Por favor, faça isto antes de iniciar \"{0}\"!"
msgstr "Muitos rastreadores no I2P exigem que você registre novos torrents antes de poder semeá-los. Por favor, faça isto antes de iniciar \"{0}\"!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:607
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Error ao criar o torrent \"{0}\""
msgstr "Erro ao criar o torrent \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:610
#, java-format
@@ -406,7 +406,7 @@ msgstr "Não se pode criar um torrent para dados que não existam: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:613
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Error ao criar o torrent - Tens que especificar um arquivo ou uma pasta."
msgstr "Erro ao criar o torrent - Tens que especificar um arquivo ou uma pasta."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:616
msgid "Stopping all torrents and closing the I2P tunnel."
@@ -424,7 +424,7 @@ msgstr "Abrendo o túnel I2P e iniciando os torrents ..."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:764
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:770
msgid "Tracker Error"
msgstr "Error do rastreador"
msgstr "Erro do rastreador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:762
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:766
@@ -443,7 +443,7 @@ msgstr[1] "{0} pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:775
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:780
msgid "Seeding"
msgstr "sembrando"
msgstr "semeando"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:784
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1533
@@ -453,7 +453,7 @@ msgstr "completo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:792
msgid "OK"
msgstr "Bien"
msgstr "bem"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801
@@ -545,7 +545,7 @@ msgstr "desconhecido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
msgid "Seed"
msgstr "Sembrador"
msgstr "Semeador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1019
msgid "Uninteresting (The peer has no pieces we need)"
@@ -595,11 +595,11 @@ msgstr "Criar um torrent"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1134
msgid "Data to seed"
msgstr "Dados para sembrar"
msgstr "Dados para semear"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1138
msgid "File or directory to seed (must be within the specified path)"
msgstr "Arquivo ou pasta para sembrar (deve estar no caminho especificado)"
msgstr "Arquivo ou pasta para semear (deve estar no caminho especificado)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1140
msgid "Tracker"

View File

@@ -16,6 +16,7 @@ import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.concurrent.RejectedExecutionException;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
@@ -228,7 +229,15 @@ class HTTPResponseOutputStream extends FilterOutputStream {
//out.flush();
PipedInputStream pi = new PipedInputStream();
PipedOutputStream po = new PipedOutputStream(pi);
new I2PAppThread(new Pusher(pi, out), "HTTP decompressor").start();
// Run in the client thread pool, as there should be an unused thread
// there after the accept().
// Overridden in I2PTunnelHTTPServer, where it does not use the client pool.
try {
I2PTunnelClientBase._executor.execute(new Pusher(pi, out));
} catch (RejectedExecutionException ree) {
// shouldn't happen
throw ree;
}
out = po;
}

View File

@@ -16,8 +16,6 @@ import net.i2p.util.Log;
public class I2PTunnelClient extends I2PTunnelClientBase {
private static final Log _log = new Log(I2PTunnelClient.class);
/** list of Destination objects that we point at */
protected List<Destination> dests;
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000; // -1

View File

@@ -17,6 +17,13 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
@@ -34,9 +41,9 @@ import net.i2p.util.SimpleTimer;
public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runnable {
private static final Log _log = new Log(I2PTunnelClientBase.class);
protected I2PAppContext _context;
protected Logging l;
protected final Log _log;
protected final I2PAppContext _context;
protected final Logging l;
static final long DEFAULT_CONNECT_TIMEOUT = 60 * 1000;
@@ -64,35 +71,24 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private String handlerName;
private String privKeyFile;
// private Object conLock = new Object();
/** List of Socket for those accept()ed but not yet started up */
protected final List _waitingSockets = new ArrayList(4); // 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? */
private int _maxWaitTime;
/**
* How many concurrent connections this I2PTunnel instance will allow to be
* in the process of connecting (or if less than 1, there is no limit)?
*/
public static final String PROP_NUM_CONNECTION_BUILDERS = "i2ptunnel.numConnectionBuilders";
/**
* How long will we let a socket wait after being accept()ed without getting
* pumped through a connection builder (in milliseconds). If this time is
* reached, the socket is unceremoniously closed and discarded. If the max
* wait time is less than 1, there is no limit.
*
*/
public static final String PROP_MAX_WAIT_TIME = "i2ptunnel.maxWaitTime";
private static final int DEFAULT_NUM_CONNECTION_BUILDERS = 5;
private static final int DEFAULT_MAX_WAIT_TIME = 30*1000;
// true if we are chained from a server.
private boolean chained = false;
/** how long to wait before dropping an idle thread */
private static final long HANDLER_KEEPALIVE_MS = 2*60*1000;
/**
* We keep a static pool of socket handlers for all clients,
* as there is no need for isolation on the client side.
* Extending classes may use it for other purposes.
* Not for use by servers, as there is no limit on threads.
*/
static final Executor _executor;
private static int _executorThreadCount;
static {
_executor = new CustomThreadPoolExecutor();
}
public I2PTunnelClientBase(int localPort, Logging l, I2PSocketManager sktMgr,
I2PTunnel tunnel, EventDispatcher notifyThis, long clientId )
throws IllegalArgumentException {
@@ -102,16 +98,16 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
_clientId = clientId;
this.localPort = localPort;
this.l = l;
this.handlerName = handlerName + _clientId;
this.handlerName = localPort + " #" + _clientId;
_ownDest = true; // == ! shared client
_context = tunnel.getContext();
_context.statManager().createRateStat("i2ptunnel.client.closeBacklog", "How many pending sockets remain when we close one due to backlog?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.client.closeNoBacklog", "How many pending sockets remain when it was removed prior to backlog timeout?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_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 });
_log = _context.logManager().getLog(getClass());
Thread t = new I2PAppThread(this);
t.setName("Client " + _clientId);
Thread t = new I2PAppThread(this, "Client " + tunnel.listenHost + ':' + localPort);
listenerReady = false;
t.start();
open = true;
@@ -125,8 +121,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
configurePool(tunnel);
if (open && listenerReady) {
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort);
notifyEvent("openBaseClientResult", "ok");
@@ -135,6 +129,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
notifyEvent("openBaseClientResult", "error");
}
}
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
EventDispatcher notifyThis, String handlerName,
I2PTunnel tunnel) throws IllegalArgumentException {
@@ -163,6 +158,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
_context.statManager().createRateStat("i2ptunnel.client.closeNoBacklog", "How many pending sockets remain when it was removed prior to backlog timeout?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_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 });
_log = _context.logManager().getLog(getClass());
// normalize path so we can find it
if (pkf != null) {
@@ -210,8 +206,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
configurePool(tunnel);
if (open && listenerReady) {
if (openNow)
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort);
@@ -224,37 +218,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
/**
* build and configure the pool handling accept()ed but not yet
* established connections
*
*/
private void configurePool(I2PTunnel tunnel) {
//_waitingSockets = new ArrayList(4);
Properties opts = tunnel.getClientOptions();
String maxWait = opts.getProperty(PROP_MAX_WAIT_TIME, DEFAULT_MAX_WAIT_TIME+"");
try {
_maxWaitTime = Integer.parseInt(maxWait);
} catch (NumberFormatException nfe) {
_maxWaitTime = DEFAULT_MAX_WAIT_TIME;
}
String numBuild = opts.getProperty(PROP_NUM_CONNECTION_BUILDERS, DEFAULT_NUM_CONNECTION_BUILDERS+"");
try {
_numConnectionBuilders = Integer.parseInt(numBuild);
} catch (NumberFormatException nfe) {
_numConnectionBuilders = DEFAULT_NUM_CONNECTION_BUILDERS;
}
for (int i = 0; i < _numConnectionBuilders; i++) {
String name = "ClientBuilder" + _clientId + '.' + i;
I2PAppThread b = new I2PAppThread(new TunnelConnectionBuilder(), name);
b.setDaemon(true);
b.start();
}
}
/**
* Sets the this.sockMgr field if it is null, or if we want a new one
*
@@ -321,6 +284,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* badly that we cant create a socketManager
*/
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
// shadows instance _log
Log _log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class);
if (socketManager != null) {
I2PSession s = socketManager.getSession();
if ( (s == null) || (s.isClosed()) ) {
@@ -378,6 +343,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* badly that we cant create a socketManager
*/
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel, String pkf, Logging log) {
// shadows instance _log
Log _log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class);
Properties props = new Properties();
props.putAll(tunnel.getClientOptions());
int portNum = 7654;
@@ -537,7 +504,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
synchronized (this) {
notifyAll();
}
synchronized (_waitingSockets) { _waitingSockets.notifyAll(); }
return;
}
ss = new ServerSocket(localPort, 0, addr);
@@ -566,12 +532,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
while (true) {
while (open) {
Socket s = ss.accept();
long before = System.currentTimeMillis();
manageConnection(s);
long total = System.currentTimeMillis() - before;
_context.statManager().addRateData("i2ptunnel.client.manageTime", total, total);
}
} catch (IOException ex) {
if (open) {
@@ -586,9 +549,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
notifyAll();
}
}
synchronized (_waitingSockets) {
_waitingSockets.notifyAll();
}
}
/**
@@ -598,24 +558,38 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
*/
protected void manageConnection(Socket s) {
if (s == null) return;
if (_numConnectionBuilders <= 0) {
new I2PAppThread(new BlockingRunner(s), "Clinet run").start();
return;
try {
_executor.execute(new BlockingRunner(s));
} catch (RejectedExecutionException ree) {
// should never happen, we have an unbounded pool and never stop the executor
try {
s.close();
} catch (IOException ioe) {}
}
if (_maxWaitTime > 0)
SimpleScheduler.getInstance().addEvent(new CloseEvent(s), _maxWaitTime);
}
synchronized (_waitingSockets) {
_waitingSockets.add(s);
_waitingSockets.notifyAll();
/**
* Not really needed for now but in case we want to add some hooks like afterExecute().
*/
private static class CustomThreadPoolExecutor extends ThreadPoolExecutor {
public CustomThreadPoolExecutor() {
super(0, Integer.MAX_VALUE, HANDLER_KEEPALIVE_MS, TimeUnit.MILLISECONDS,
new SynchronousQueue(), new CustomThreadFactory());
}
}
/** just to set the name and set Daemon */
private static class CustomThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread rv = Executors.defaultThreadFactory().newThread(r);
rv.setName("I2PTunnel Client Runner " + (++_executorThreadCount));
rv.setDaemon(true);
return rv;
}
}
/**
* Blocking runner, used during the connection establishment whenever we
* are not using the queued builders.
*
* Blocking runner, used during the connection establishment
*/
private class BlockingRunner implements Runnable {
private Socket _s;
@@ -625,32 +599,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
/**
* Remove and close the socket from the waiting list, if it is still there.
*
*/
private class CloseEvent implements SimpleTimer.TimedEvent {
private Socket _s;
public CloseEvent(Socket s) { _s = s; }
public void timeReached() {
int remaining = 0;
boolean stillWaiting = false;
synchronized (_waitingSockets) {
stillWaiting = _waitingSockets.remove(_s);
remaining = _waitingSockets.size();
}
if (stillWaiting) {
try { _s.close(); } catch (IOException ioe) {}
if (_log.shouldLog(Log.INFO)) {
_context.statManager().addRateData("i2ptunnel.client.closeBacklog", remaining, 0);
_log.info("Closed a waiting socket because of backlog");
}
} else {
_context.statManager().addRateData("i2ptunnel.client.closeNoBacklog", remaining, 0);
}
}
}
public boolean close(boolean forced) {
if (_log.shouldLog(Log.INFO))
_log.info("close() called: forced = " + forced + " open = " + open + " sockMgr = " + sockMgr);
@@ -688,7 +636,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
//l.log("Client closed.");
}
synchronized (_waitingSockets) { _waitingSockets.notifyAll(); }
return true;
}
@@ -696,40 +643,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
try {
s.close();
} catch (IOException ex) {
_log.error("Could not close socket", ex);
//_log.error("Could not close socket", ex);
}
}
/**
* Pool runner pulling sockets off the waiting list and pushing them
* through clientConnectionRun. This dies when the I2PTunnel instance
* is closed.
*
*/
private class TunnelConnectionBuilder implements Runnable {
public void run() {
Socket s = null;
while (open) {
try {
synchronized (_waitingSockets) {
if (_waitingSockets.isEmpty())
_waitingSockets.wait();
else
s = (Socket)_waitingSockets.remove(0);
}
} catch (InterruptedException ie) {}
if (s != null) {
long before = System.currentTimeMillis();
clientConnectionRun(s);
long total = System.currentTimeMillis() - before;
_context.statManager().addRateData("i2ptunnel.client.buildRunTime", total, 0);
}
s = null;
}
}
}
/**
* Manage a connection in a separate thread. This only works if
* you do not override manageConnection()

View File

@@ -58,7 +58,6 @@ import net.i2p.util.Log;
* @author zzz a stripped-down I2PTunnelHTTPClient
*/
public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelConnectClient.class);
private final static byte[] ERR_DESTINATION_UNKNOWN =
("HTTP/1.1 503 Service Unavailable\r\n"+
@@ -340,8 +339,8 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
_requestId = id;
}
public void run() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Timeout occured requesting " + _target);
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Timeout occured requesting " + _target);
handleConnectClientException(new RuntimeException("Timeout"), _out,
_target, _usingProxy, _wwwProxy, _requestId);
closeSocket(_socket);

View File

@@ -11,7 +11,6 @@ import net.i2p.util.EventDispatcher;
import net.i2p.util.Log;
public class I2PTunnelHTTPBidirServer extends I2PTunnelHTTPServer {
private final static Log log = new Log(I2PTunnelHTTPBidirServer.class);
public I2PTunnelHTTPBidirServer(InetAddress host, int port, int proxyport, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, spoofHost, l, notifyThis, tunnel);

View File

@@ -61,7 +61,6 @@ import net.i2p.util.Translate;
*
*/
public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelHTTPClient.class);
private HashMap addressHelpers = new HashMap();
@@ -894,15 +893,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
_requestId = id;
}
public void run() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Timeout occured requesting " + _target);
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Timeout occured requesting " + _target);
handleHTTPClientException(new RuntimeException("Timeout"), _out,
_target, _usingProxy, _wwwProxy, _requestId);
closeSocket(_socket);
}
}
private static String DEFAULT_JUMP_SERVERS =
public static final String DEFAULT_JUMP_SERVERS =
"http://i2host.i2p/cgi-bin/i2hostjump?," +
"http://stats.i2p/cgi-bin/jump.cgi?a=," +
"http://i2jump.i2p/";
@@ -940,8 +939,12 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
// Skip jump servers we don't know
String jumphost = jurl.substring(7); // "http://"
jumphost = jumphost.substring(0, jumphost.indexOf('/'));
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(jumphost);
if (dest == null) continue;
if (!jumphost.endsWith(".i2p"))
continue;
if (!jumphost.endsWith(".b32.i2p")) {
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(jumphost);
if (dest == null) continue;
}
out.write("<br><a href=\"".getBytes());
out.write(jurl.getBytes());

View File

@@ -25,7 +25,7 @@ import net.i2p.util.Log;
* @since 0.8.2
*/
public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelHTTPClientBase.class);
protected final List<String> _proxyList;
protected final static byte[] ERR_NO_OUTPROXY =

View File

@@ -31,7 +31,7 @@ import net.i2p.data.Base32;
*
*/
public class I2PTunnelHTTPServer extends I2PTunnelServer {
private final static Log _log = new Log(I2PTunnelHTTPServer.class);
/** what Host: should we seem to be to the webserver? */
private String _spoofHost;
private static final String HASH_HEADER = "X-I2P-DestHash";
@@ -40,6 +40,20 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
private static final String[] CLIENT_SKIPHEADERS = {HASH_HEADER, DEST64_HEADER, DEST32_HEADER};
private static final String SERVER_HEADER = "Server";
private static final String[] SERVER_SKIPHEADERS = {SERVER_HEADER};
private static final long HEADER_TIMEOUT = 60*1000;
private final static byte[] ERR_UNAVAILABLE =
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"Connection: close\r\n"+
"Proxy-Connection: close\r\n"+
"\r\n"+
"<html><head><title>503 Service Unavailable<title></head>\n"+
"<body><h2>503 Service Unavailable</h2>\n" +
"<p>This I2P eepsite is unavailable. It may be down or undergoing maintenance.</p>\n" +
"</body></html>")
.getBytes();
public I2PTunnelHTTPServer(InetAddress host, int port, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, l, notifyThis, tunnel);
@@ -73,8 +87,9 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
//local is fast, so synchronously. Does not need that many
//threads.
try {
// give them 5 seconds to send in the HTTP request
socket.setReadTimeout(5*1000);
// The headers _should_ be in the first packet, but
// may not be, depending on the client-side options
socket.setReadTimeout(HEADER_TIMEOUT);
InputStream in = socket.getInputStream();
@@ -124,19 +139,30 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
if (allowGZIP && useGZIP) {
I2PAppThread req = new I2PAppThread(
new CompressedRequestor(s, socket, modifiedHeader, getTunnel().getContext()),
new CompressedRequestor(s, socket, modifiedHeader, getTunnel().getContext(), _log),
Thread.currentThread().getName()+".hc");
req.start();
} else {
new I2PTunnelRunner(s, socket, slock, null, modifiedHeader.getBytes(), null);
}
long afterHandle = getTunnel().getContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
getTunnel().getContext().statManager().addRateData("i2ptunnel.httpserver.blockingHandleTime", timeToHandle, 0);
if ( (timeToHandle > 1000) && (_log.shouldLog(Log.WARN)) )
_log.warn("Took a while to handle the request for " + remoteHost + ':' + remotePort +
" [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
} catch (SocketException ex) {
try {
// Send a 503, so the user doesn't get an HTTP Proxy error message
// and blame his router or the network.
socket.getOutputStream().write(ERR_UNAVAILABLE);
} catch (IOException ioe) {}
try {
socket.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error while closing the received i2p con", ex);
}
} catch (IOException ioe) {}
if (_log.shouldLog(Log.ERROR))
_log.error("Error connecting to HTTP server " + remoteHost + ':' + remotePort, ex);
} catch (IOException ex) {
try {
socket.close();
@@ -150,25 +176,24 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
if (_log.shouldLog(Log.ERROR))
_log.error("OOM in HTTP server", oom);
}
long afterHandle = getTunnel().getContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
getTunnel().getContext().statManager().addRateData("i2ptunnel.httpserver.blockingHandleTime", timeToHandle, 0);
if ( (timeToHandle > 1000) && (_log.shouldLog(Log.WARN)) )
_log.warn("Took a while to handle the request [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
}
private static class CompressedRequestor implements Runnable {
private Socket _webserver;
private I2PSocket _browser;
private String _headers;
private I2PAppContext _ctx;
public CompressedRequestor(Socket webserver, I2PSocket browser, String headers, I2PAppContext ctx) {
private final Socket _webserver;
private final I2PSocket _browser;
private final String _headers;
private final I2PAppContext _ctx;
// shadows _log in super()
private final Log _log;
public CompressedRequestor(Socket webserver, I2PSocket browser, String headers, I2PAppContext ctx, Log log) {
_webserver = webserver;
_browser = browser;
_headers = headers;
_ctx = ctx;
_log = log;
}
public void run() {
if (_log.shouldLog(Log.INFO))
_log.info("Compressed requestor running");
@@ -183,7 +208,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
_log.info("request headers: " + _headers);
serverout.write(_headers.getBytes());
browserin = _browser.getInputStream();
I2PAppThread sender = new I2PAppThread(new Sender(serverout, browserin, "server: browser to server"), Thread.currentThread().getName() + "hcs");
I2PAppThread sender = new I2PAppThread(new Sender(serverout, browserin, "server: browser to server", _log), Thread.currentThread().getName() + "hcs");
sender.start();
browserout = _browser.getOutputStream();
@@ -214,7 +239,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
String modifiedHeaders = formatHeaders(headers, command);
compressedOut.write(modifiedHeaders.getBytes());
Sender s = new Sender(compressedOut, serverin, "server: server to browser");
Sender s = new Sender(compressedOut, serverin, "server: server to browser", _log);
if (_log.shouldLog(Log.INFO))
_log.info("Before pumping the compressed response");
s.run(); // same thread
@@ -233,14 +258,19 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
private static class Sender implements Runnable {
private OutputStream _out;
private InputStream _in;
private String _name;
public Sender(OutputStream out, InputStream in, String name) {
private final OutputStream _out;
private final InputStream _in;
private final String _name;
// shadows _log in super()
private final Log _log;
public Sender(OutputStream out, InputStream in, String name, Log log) {
_out = out;
_in = in;
_name = name;
_log = log;
}
public void run() {
if (_log.shouldLog(Log.INFO))
_log.info(_name + ": Begin sending");
@@ -277,16 +307,16 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
protected boolean shouldCompress() { return true; }
@Override
protected void finishHeaders() throws IOException {
if (_log.shouldLog(Log.INFO))
_log.info("Including x-i2p-gzip as the content encoding in the response");
//if (_log.shouldLog(Log.INFO))
// _log.info("Including x-i2p-gzip as the content encoding in the response");
out.write("Content-encoding: x-i2p-gzip\r\n".getBytes());
super.finishHeaders();
}
@Override
protected void beginProcessing() throws IOException {
if (_log.shouldLog(Log.INFO))
_log.info("Beginning compression processing");
//if (_log.shouldLog(Log.INFO))
// _log.info("Beginning compression processing");
//out.flush();
_gzipOut = new InternalGZIPOutputStream(out);
out = _gzipOut;
@@ -352,8 +382,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
boolean ok = DataHelper.readLine(in, command);
if (!ok) throw new IOException("EOF reached while reading the HTTP command [" + command.toString() + "]");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Read the http command [" + command.toString() + "]");
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Read the http command [" + command.toString() + "]");
// FIXME we probably don't need or want this in the outgoing direction
int trimmed = 0;
@@ -409,8 +439,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
headers.setProperty(name, value);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Read the header [" + name + "] = [" + value + "]");
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Read the header [" + name + "] = [" + value + "]");
}
}
}

View File

@@ -20,8 +20,6 @@ import net.i2p.util.Log;
*/
public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelIRCClient.class);
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
@@ -130,6 +128,8 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
private Socket local;
private I2PSocket remote;
private StringBuffer expectedPong;
// shadows _log in super()
private final Log _log = new Log(I2PTunnelIRCClient.class);
public IrcInboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong) {
local=_local;
@@ -207,6 +207,8 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
private Socket local;
private I2PSocket remote;
private StringBuffer expectedPong;
// shadows _log in super()
private final Log _log = new Log(I2PTunnelIRCClient.class);
public IrcOutboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong) {
local=_local;
@@ -308,7 +310,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
try { command = field[idx++]; }
catch (IndexOutOfBoundsException ioobe) // wtf, server sent borked command?
{
_log.warn("Dropping defective message: index out of bounds while extracting command.");
//_log.warn("Dropping defective message: index out of bounds while extracting command.");
return null;
}
@@ -431,13 +433,13 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
rv = "PING " + field[1];
expectedPong.append("PONG ").append(field[2]).append(" :").append(field[1]); // PONG serverLocation nonce
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("IRC client sent a PING we don't understand, filtering it (\"" + s + "\")");
//if (_log.shouldLog(Log.ERROR))
// _log.error("IRC client sent a PING we don't understand, filtering it (\"" + s + "\")");
rv = null;
}
if (_log.shouldLog(Log.WARN))
_log.warn("sending ping [" + rv + "], waiting for [" + expectedPong + "] orig was [" + s + "]");
//if (_log.shouldLog(Log.WARN))
// _log.warn("sending ping [" + rv + "], waiting for [" + expectedPong + "] orig was [" + s + "]");
return rv;
}

View File

@@ -61,9 +61,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
public static final String PROP_WEBIRC_SPOOF_IP_DEFAULT="127.0.0.1";
public static final String PROP_HOSTNAME="ircserver.fakeHostname";
public static final String PROP_HOSTNAME_DEFAULT="%f.b32.i2p";
private static final Log _log = new Log(I2PTunnelIRCServer.class);
private static final long HEADER_TIMEOUT = 60*1000;
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
@@ -108,8 +106,9 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
try {
String modifiedRegistration;
if(!this.method.equals("webirc")) {
// give them 15 seconds to send in the request
socket.setReadTimeout(15*1000);
// The headers _should_ be in the first packet, but
// may not be, depending on the client-side options
socket.setReadTimeout(HEADER_TIMEOUT);
InputStream in = socket.getInputStream();
modifiedRegistration = filterRegistration(in, cloakDest(socket.getPeerDestination()));
socket.setReadTimeout(readTimeout);
@@ -126,12 +125,12 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
Socket s = new Socket(remoteHost, remotePort);
new I2PTunnelRunner(s, socket, slock, null, modifiedRegistration.getBytes(), null);
} catch (SocketException ex) {
// TODO send the equivalent of a 503?
try {
socket.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error while closing the received i2p con", ex);
}
} catch (IOException ioe) {}
if (_log.shouldLog(Log.ERROR))
_log.error("Error connecting to IRC server " + remoteHost + ':' + remotePort, ex);
} catch (IOException ex) {
try {
socket.close();
@@ -181,8 +180,8 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
if (++lineCount > 10)
throw new IOException("Too many lines before USER or SERVER, giving up");
s = s.trim();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got line: " + s);
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Got line: " + s);
String field[]=s.split(" ",5);
String command;
@@ -214,8 +213,8 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
if ("SERVER".equalsIgnoreCase(command))
break;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("All done, sending: " + buf.toString());
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("All done, sending: " + buf.toString());
return buf.toString();
}

View File

@@ -16,6 +16,12 @@ import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
@@ -30,8 +36,7 @@ import net.i2p.util.Log;
public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
private final static Log _log = new Log(I2PTunnelServer.class);
protected final Log _log;
protected I2PSocketManager sockMgr;
protected I2PServerSocket i2pss;
@@ -48,12 +53,17 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
/** default timeout to 3 minutes - override if desired */
protected long readTimeout = DEFAULT_READ_TIMEOUT;
private static final boolean DEFAULT_USE_POOL = false;
/** do we use threads? default true (ignored for standard servers, always false) */
private static final String PROP_USE_POOL = "i2ptunnel.usePool";
private static final boolean DEFAULT_USE_POOL = true;
protected static volatile long __serverId = 0;
/** max number of threads - this many slowlorisses will DOS this server, but too high could OOM the JVM */
private static final String PROP_HANDLER_COUNT = "i2ptunnel.blockingHandlerCount";
private static final int DEFAULT_HANDLER_COUNT = 10;
private static final int DEFAULT_HANDLER_COUNT = 65;
/** min number of threads */
private static final int MIN_HANDLERS = 0;
/** how long to wait before dropping an idle thread */
private static final long HANDLER_KEEPALIVE_MS = 30*1000;
protected I2PTunnelTask task = null;
protected boolean bidir = false;
@@ -67,8 +77,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
*/
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super("Server at " + host + ':' + port, notifyThis, tunnel);
_log = tunnel.getContext().logManager().getLog(getClass());
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(privData));
SetUsePool(tunnel);
init(host, port, bais, privData, l);
}
@@ -79,7 +89,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis, I2PTunnel tunnel) {
super("Server at " + host + ':' + port, notifyThis, tunnel);
SetUsePool(tunnel);
_log = tunnel.getContext().logManager().getLog(getClass());
FileInputStream fis = null;
try {
fis = new FileInputStream(privkey);
@@ -99,19 +109,10 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
*/
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super("Server at " + host + ':' + port, notifyThis, tunnel);
SetUsePool(tunnel);
_log = tunnel.getContext().logManager().getLog(getClass());
init(host, port, privData, privkeyname, l);
}
private void SetUsePool(I2PTunnel Tunnel) {
String usePool = Tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
}
private static final int RETRY_DELAY = 20*1000;
private static final int MAX_RETRIES = 4;
@@ -143,6 +144,16 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
return;
}
// extending classes default to threaded, but for a standard server, we can't get slowlorissed
_usePool = !getClass().equals(I2PTunnelServer.class);
if (_usePool) {
String usePool = getTunnel().getClientOptions().getProperty(PROP_USE_POOL);
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
}
// Todo: Can't stop a tunnel from the UI while it's in this loop (no session yet)
int retries = 0;
while (sockMgr == null) {
@@ -199,8 +210,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
*
*/
public void startRunning() {
Thread t = new I2PAppThread(this);
t.setName("Server " + (++__serverId));
Thread t = new I2PAppThread(this, "Server " + remoteHost + ':' + remotePort, true);
t.start();
}
@@ -236,7 +246,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
return false;
}
l.log("Stopping tunnels for server at " + getTunnel().listenHost + ':' + this.remotePort);
l.log("Stopping tunnels for server at " + this.remoteHost + ':' + this.remotePort);
try {
if (i2pss != null) i2pss.close();
getTunnel().removeSession(sockMgr.getSession());
@@ -259,67 +269,106 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
rv = Integer.parseInt(cnt);
if (rv <= 0)
rv = DEFAULT_HANDLER_COUNT;
} catch (NumberFormatException nfe) {
rv = DEFAULT_HANDLER_COUNT;
}
} catch (NumberFormatException nfe) {}
}
return rv;
}
/**
* If usePool is set, this starts the executor pool.
* Then, do the accept() loop, and either
* hands each I2P socket to the executor or runs it in-line.
*/
public void run() {
if (shouldUsePool()) {
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
int handlers = getHandlerCount();
for (int i = 0; i < handlers; i++) {
I2PAppThread handler = new I2PAppThread(new Handler(i2pS_S), "Handle Server " + i);
handler.start();
}
} else {
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
while (true) {
try {
final I2PSocket i2ps = i2pS_S.accept();
if (i2ps == null) throw new I2PException("I2PServerSocket closed");
new I2PAppThread(new Runnable() { public void run() { blockingHandle(i2ps); } }).start();
} catch (I2PException ipe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting - KILLING THE TUNNEL SERVER", ipe);
return;
} catch (ConnectException ce) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting", ce);
// not killing the server..
} catch(SocketTimeoutException ste) {
// ignored, we never set the timeout
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
ThreadPoolExecutor executor = null;
if (_log.shouldLog(Log.WARN)) {
if (_usePool)
_log.warn("Starting executor with " + getHandlerCount() + " threads max");
else
_log.warn("Threads disabled, running blockingHandles inline");
}
if (_usePool) {
executor = new CustomThreadPoolExecutor(getHandlerCount(), "ServerHandler pool " + remoteHost + ':' + remotePort);
}
while (open) {
try {
final I2PSocket i2ps = i2pS_S.accept();
if (i2ps == null) throw new I2PException("I2PServerSocket closed");
if (_usePool) {
try {
executor.execute(new Handler(i2ps));
} catch (RejectedExecutionException ree) {
try {
i2ps.close();
} catch (IOException ioe) {}
if (open && _log.shouldLog(Log.ERROR))
_log.error("ServerHandler queue full for " + remoteHost + ':' + remotePort +
"; increase " + PROP_HANDLER_COUNT + '?', ree);
}
} else {
// use only for standard servers that can't get slowlorissed! Not for http or irc
blockingHandle(i2ps);
}
} catch (I2PException ipe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting - KILLING THE TUNNEL SERVER", ipe);
return;
} catch (ConnectException ce) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting", ce);
// not killing the server..
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException ie) {}
} catch(SocketTimeoutException ste) {
// ignored, we never set the timeout
}
}
if (executor != null)
executor.shutdownNow();
}
/**
* Not really needed for now but in case we want to add some hooks like afterExecute().
*/
private static class CustomThreadPoolExecutor extends ThreadPoolExecutor {
public CustomThreadPoolExecutor(int max, String name) {
super(MIN_HANDLERS, max, HANDLER_KEEPALIVE_MS, TimeUnit.MILLISECONDS,
new SynchronousQueue(), new CustomThreadFactory(name));
}
}
/** just to set the name and set Daemon */
private static class CustomThreadFactory implements ThreadFactory {
private String _name;
public CustomThreadFactory(String name) {
_name = name;
}
public Thread newThread(Runnable r) {
Thread rv = Executors.defaultThreadFactory().newThread(r);
rv.setName(_name);
rv.setDaemon(true);
return rv;
}
}
public boolean shouldUsePool() { return _usePool; }
/**
* minor thread pool to pull off the accept() concurrently. there are still lots
* (and lots) of wasted threads within the I2PTunnelRunner, but its a start
*
* Run the blockingHandler.
*/
private class Handler implements Runnable {
private I2PServerSocket _serverSocket;
public Handler(I2PServerSocket serverSocket) {
_serverSocket = serverSocket;
private I2PSocket _i2ps;
public Handler(I2PSocket socket) {
_i2ps = socket;
}
public void run() {
while (open) {
try {
blockingHandle(_serverSocket.accept());
} catch (I2PException ex) {
_log.error("Error while waiting for I2PConnections", ex);
return;
} catch (IOException ex) {
_log.error("Error while waiting for I2PConnections", ex);
return;
}
}
blockingHandle(_i2ps);
}
}
@@ -335,20 +384,21 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
Socket s = new Socket(remoteHost, remotePort);
afterSocket = I2PAppContext.getGlobalContext().clock().now();
new I2PTunnelRunner(s, socket, slock, null, null);
long afterHandle = I2PAppContext.getGlobalContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
if ( (timeToHandle > 1000) && (_log.shouldLog(Log.WARN)) )
_log.warn("Took a while to handle the request for " + remoteHost + ':' + remotePort +
" [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
} catch (SocketException ex) {
try {
socket.close();
} catch (IOException ioe) {
_log.error("Error while closing the received i2p con", ex);
}
} catch (IOException ioe) {}
if (_log.shouldLog(Log.ERROR))
_log.error("Error connecting to server " + remoteHost + ':' + remotePort, ex);
} catch (IOException ex) {
_log.error("Error while waiting for I2PConnections", ex);
}
long afterHandle = I2PAppContext.getGlobalContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
if (timeToHandle > 1000)
_log.warn("Took a while to handle the request [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
}
}

View File

@@ -259,10 +259,9 @@ public class TunnelController implements Logging {
/*
* Streamr client is a UDP server, use the listenPort field for targetPort
* and the listenOnInterface field for the targetHost
*/
private void startStreamrClient() {
String targetHost = getListenOnInterface();
String targetHost = getTargetHost();
String targetPort = getListenPort();
String dest = getTargetDestination();
_tunnel.runStreamrClient(new String[] { targetHost, targetPort, dest }, this);
@@ -270,10 +269,9 @@ public class TunnelController implements Logging {
/**
* Streamr server is a UDP client, use the targetPort field for listenPort
* and the targetHost field for the listenOnInterface
*/
private void startStreamrServer() {
String listenOn = getTargetHost();
String listenOn = getListenOnInterface();
if ( (listenOn != null) && (listenOn.length() > 0) ) {
_tunnel.runListenOn(new String[] { listenOn }, this);
}

View File

@@ -30,7 +30,6 @@ import net.i2p.util.Log;
*/
public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel {
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PSOCKSIRCTunnel.class);
private static int __clientId = 0;
/** @param pkf private key file name or null for transient key */

View File

@@ -26,7 +26,6 @@ import net.i2p.util.Log;
public class I2PSOCKSTunnel extends I2PTunnelClientBase {
private static final Log _log = new Log(I2PSOCKSTunnel.class);
private HashMap<String, List<String>> proxies = null; // port# + "" or "default" -> hostname list
protected Destination outProxyDest = null;

View File

@@ -45,7 +45,6 @@ import net.i2p.util.Log;
*/
public abstract class I2PTunnelUDPClientBase extends I2PTunnelTask implements Source, Sink {
private static final Log _log = new Log(I2PTunnelUDPClientBase.class);
protected I2PAppContext _context;
protected Logging l;

View File

@@ -46,7 +46,7 @@ import net.i2p.util.Log;
public class I2PTunnelUDPServerBase extends I2PTunnelTask implements Source, Sink {
private final static Log _log = new Log(I2PTunnelUDPServerBase.class);
private final Log _log;
private final Object lock = new Object();
protected Object slock = new Object();
@@ -73,6 +73,7 @@ public class I2PTunnelUDPServerBase extends I2PTunnelTask implements Source, Sin
public I2PTunnelUDPServerBase(boolean verify, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis, I2PTunnel tunnel) {
super("UDPServer <- " + privkeyname, notifyThis, tunnel);
_log = tunnel.getContext().logManager().getLog(I2PTunnelUDPServerBase.class);
FileInputStream fis = null;
try {
fis = new FileInputStream(privkey);

View File

@@ -12,15 +12,18 @@ import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Set;
import net.i2p.data.Base64;
import net.i2p.data.Destination;
import net.i2p.data.PrivateKeyFile;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
import net.i2p.util.Addresses;
/**
* Ugly little accessor for the edit page
@@ -171,14 +174,23 @@ public class EditBean extends IndexBean {
return getProperty(tunnel, "i2cp.leaseSetKey", "");
}
public boolean getAccess(int tunnel) {
return getBooleanProperty(tunnel, "i2cp.enableAccessList");
public String getAccessMode(int tunnel) {
if (getBooleanProperty(tunnel, PROP_ENABLE_ACCESS_LIST))
return "1";
if (getBooleanProperty(tunnel, PROP_ENABLE_BLACKLIST))
return "2";
return "0";
}
public String getAccessList(int tunnel) {
return getProperty(tunnel, "i2cp.accessList", "").replace(",", "\n");
}
public String getJumpList(int tunnel) {
return getProperty(tunnel, I2PTunnelHTTPClient.PROP_JUMP_SERVERS,
I2PTunnelHTTPClient.DEFAULT_JUMP_SERVERS).replace(",", "\n");
}
public boolean getClose(int tunnel) {
return getBooleanProperty(tunnel, "i2cp.closeOnIdle");
}
@@ -234,6 +246,35 @@ public class EditBean extends IndexBean {
return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW, "");
}
/** all of these are @since 0.8.3 */
public String getLimitMinute(int tunnel) {
return getProperty(tunnel, PROP_MAX_CONNS_MIN, "0");
}
public String getLimitHour(int tunnel) {
return getProperty(tunnel, PROP_MAX_CONNS_HOUR, "0");
}
public String getLimitDay(int tunnel) {
return getProperty(tunnel, PROP_MAX_CONNS_DAY, "0");
}
public String getTotalMinute(int tunnel) {
return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_MIN, "0");
}
public String getTotalHour(int tunnel) {
return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_HOUR, "0");
}
public String getTotalDay(int tunnel) {
return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_DAY, "0");
}
public String getMaxStreams(int tunnel) {
return getProperty(tunnel, PROP_MAX_STREAMS, "0");
}
private int getProperty(int tunnel, String prop, int def) {
TunnelController tun = getController(tunnel);
if (tun != null) {
@@ -270,7 +311,19 @@ public class EditBean extends IndexBean {
return false;
}
/** @since 0.8.3 */
public boolean isRouterContext() {
return _context.isRouterContext();
}
/** @since 0.8.3 */
public Set<String> interfaceSet() {
return Addresses.getAllAddresses();
}
public String getI2CPHost(int tunnel) {
if (_context.isRouterContext())
return _("internal");
TunnelController tun = getController(tunnel);
if (tun != null)
return tun.getI2CPHost();
@@ -279,6 +332,8 @@ public class EditBean extends IndexBean {
}
public String getI2CPPort(int tunnel) {
if (_context.isRouterContext())
return _("internal");
TunnelController tun = getController(tunnel);
if (tun != null)
return tun.getI2CPPort();

View File

@@ -24,6 +24,7 @@ import net.i2p.data.Certificate;
import net.i2p.data.Destination;
import net.i2p.data.PrivateKeyFile;
import net.i2p.data.SessionKey;
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
@@ -62,7 +63,6 @@ public class IndexBean {
private String _proxyList;
private String _port;
private String _reachableBy;
private String _reachableByOther;
private String _targetDestination;
private String _targetHost;
private String _targetPort;
@@ -431,10 +431,13 @@ public class IndexBean {
public String getClientInterface(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
return tun.getListenOnInterface();
else
return "";
if (tun != null) {
if ("streamrclient".equals(tun.getType()))
return tun.getTargetHost();
else
return tun.getListenOnInterface();
} else
return "127.0.0.1";
}
public int getTunnelStatus(int tunnel) {
@@ -477,11 +480,38 @@ public class IndexBean {
return rv != null ? rv : "";
}
/**
* Call this to see if it is ok to linkify getServerTarget()
* @since 0.8.3
*/
public boolean isServerTargetLinkValid(int tunnel) {
TunnelController tun = getController(tunnel);
return tun != null &&
"httpserver".equals(tun.getType()) &&
tun.getTargetHost() != null &&
tun.getTargetPort() != null;
}
/**
* @return valid host:port only if isServerTargetLinkValid() is true
*/
public String getServerTarget(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
return tun.getTargetHost() + ':' + tun.getTargetPort();
else
if (tun != null) {
String host;
if ("streamrserver".equals(tun.getType()))
host = tun.getListenOnInterface();
else
host = tun.getTargetHost();
String port = tun.getTargetPort();
if (host == null)
host = "<font color=\"red\">" + _("Host not set") + "</font>";
else if (host.indexOf(':') >= 0)
host = '[' + host + ']';
if (port == null)
port = "<font color=\"red\">" + _("Port not set") + "</font>";
return host + ':' + port;
} else
return "";
}
@@ -537,11 +567,11 @@ public class IndexBean {
public void setDescription(String description) {
_description = (description != null ? description.trim() : null);
}
/** I2CP host the router is on */
/** I2CP host the router is on, ignored when in router context */
public void setClientHost(String host) {
_i2cpHost = (host != null ? host.trim() : null);
}
/** I2CP port the router is on */
/** I2CP port the router is on, ignored when in router context */
public void setClientport(String port) {
_i2cpPort = (port != null ? port.trim() : null);
}
@@ -574,19 +604,11 @@ public class IndexBean {
_port = (port != null ? port.trim() : null);
}
/**
* what interface should this client/httpclient/ircclient listen on (unless
* overridden by the setReachableByOther() field)
* what interface should this client/httpclient/ircclient listen on
*/
public void setReachableBy(String reachableBy) {
_reachableBy = (reachableBy != null ? reachableBy.trim() : null);
}
/**
* If specified, defines the exact IP interface to listen for requests
* on (in the case of client/httpclient/ircclient tunnels)
*/
public void setReachableByOther(String reachableByOther) {
_reachableByOther = (reachableByOther != null ? reachableByOther.trim() : null);
}
/** What peer does this client tunnel point at */
public void setTargetDestination(String dest) {
_targetDestination = (dest != null ? dest.trim() : null);
@@ -643,9 +665,17 @@ public class IndexBean {
public void setEncrypt(String moo) {
_booleanOptions.add("i2cp.encryptLeaseSet");
}
public void setAccess(String moo) {
_booleanOptions.add("i2cp.enableAccessList");
protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList";
protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList";
public void setAccessMode(String val) {
if ("1".equals(val))
_booleanOptions.add(PROP_ENABLE_ACCESS_LIST);
else if ("2".equals(val))
_booleanOptions.add(PROP_ENABLE_BLACKLIST);
}
public void setDelayOpen(String moo) {
_booleanOptions.add("i2cp.delayOpen");
}
@@ -671,10 +701,17 @@ public class IndexBean {
if (val != null)
_otherOptions.put("i2cp.leaseSetKey", val.trim());
}
public void setAccessList(String val) {
if (val != null)
_otherOptions.put("i2cp.accessList", val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ","));
}
public void setJumpList(String val) {
if (val != null)
_otherOptions.put(I2PTunnelHTTPClient.PROP_JUMP_SERVERS, val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ","));
}
public void setCloseTime(String val) {
if (val != null) {
try {
@@ -712,6 +749,50 @@ public class IndexBean {
_otherOptions.put(I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW, s.trim());
}
/** all of these are @since 0.8.3 */
protected static final String PROP_MAX_CONNS_MIN = "i2p.streaming.maxConnsPerMinute";
protected static final String PROP_MAX_CONNS_HOUR = "i2p.streaming.maxConnsPerHour";
protected static final String PROP_MAX_CONNS_DAY = "i2p.streaming.maxConnsPerDay";
protected static final String PROP_MAX_TOTAL_CONNS_MIN = "i2p.streaming.maxTotalConnsPerMinute";
protected static final String PROP_MAX_TOTAL_CONNS_HOUR = "i2p.streaming.maxTotalConnsPerHour";
protected static final String PROP_MAX_TOTAL_CONNS_DAY = "i2p.streaming.maxTotalConnsPerDay";
protected static final String PROP_MAX_STREAMS = "i2p.streaming.maxConcurrentStreams";
public void setLimitMinute(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_CONNS_MIN, s.trim());
}
public void setLimitHour(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_CONNS_HOUR, s.trim());
}
public void setLimitDay(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_CONNS_DAY, s.trim());
}
public void setTotalMinute(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_TOTAL_CONNS_MIN, s.trim());
}
public void setTotalHour(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_TOTAL_CONNS_HOUR, s.trim());
}
public void setTotalDay(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_TOTAL_CONNS_DAY, s.trim());
}
public void setMaxStreams(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_STREAMS, s.trim());
}
/** params needed for hashcash and dest modification */
public void setEffort(String val) {
if (val != null) {
@@ -831,17 +912,22 @@ public class IndexBean {
Properties config = new Properties();
updateConfigGeneric(config);
if ((isClient(_type) && !"streamrclient".equals(_type)) || "streamrserver".equals(_type)) {
// streamrserver uses interface
if (_reachableBy != null)
config.setProperty("interface", _reachableBy);
else
config.setProperty("interface", "");
} else {
// streamrclient uses targetHost
if (_targetHost != null)
config.setProperty("targetHost", _targetHost);
}
if (isClient(_type)) {
// generic client stuff
if (_port != null)
config.setProperty("listenPort", _port);
if (_reachableByOther != null)
config.setProperty("interface", _reachableByOther);
else if (_reachableBy != null)
config.setProperty("interface", _reachableBy);
else
config.setProperty("interface", "");
config.setProperty("sharedClient", _sharedClient + "");
for (String p : _booleanClientOpts)
config.setProperty("option." + p, "" + _booleanOptions.contains(p));
@@ -850,8 +936,6 @@ public class IndexBean {
config.setProperty("option." + p, _otherOptions.get(p));
} else {
// generic server stuff
if (_targetHost != null)
config.setProperty("targetHost", _targetHost);
if (_targetPort != null)
config.setProperty("targetPort", _targetPort);
for (String p : _booleanServerOpts)
@@ -880,9 +964,7 @@ public class IndexBean {
if ("httpbidirserver".equals(_type)) {
if (_port != null)
config.setProperty("listenPort", _port);
if (_reachableByOther != null)
config.setProperty("interface", _reachableByOther);
else if (_reachableBy != null)
if (_reachableBy != null)
config.setProperty("interface", _reachableBy);
else if (_targetHost != null)
config.setProperty("interface", _targetHost);
@@ -904,16 +986,20 @@ public class IndexBean {
I2PTunnelHTTPClientBase.PROP_AUTH, I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH
};
private static final String _booleanServerOpts[] = {
"i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", "i2cp.enableAccessList"
"i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", PROP_ENABLE_ACCESS_LIST, PROP_ENABLE_BLACKLIST
};
private static final String _otherClientOpts[] = {
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime",
"proxyUsername", "proxyPassword", "outproxyUsername", "outproxyPassword"
"proxyUsername", "proxyPassword", "outproxyUsername", "outproxyPassword",
I2PTunnelHTTPClient.PROP_JUMP_SERVERS
};
private static final String _otherServerOpts[] = {
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.leaseSetKey", "i2cp.accessList"
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.leaseSetKey", "i2cp.accessList",
PROP_MAX_CONNS_MIN, PROP_MAX_CONNS_HOUR, PROP_MAX_CONNS_DAY,
PROP_MAX_TOTAL_CONNS_MIN, PROP_MAX_TOTAL_CONNS_HOUR, PROP_MAX_TOTAL_CONNS_DAY,
PROP_MAX_STREAMS
};
protected static final Set _noShowSet = new HashSet();
protected static final Set _noShowSet = new HashSet(64);
static {
_noShowSet.addAll(Arrays.asList(_noShowOpts));
_noShowSet.addAll(Arrays.asList(_booleanClientOpts));
@@ -929,12 +1015,14 @@ public class IndexBean {
config.setProperty("name", _name);
if (_description != null)
config.setProperty("description", _description);
if (_i2cpHost != null)
config.setProperty("i2cpHost", _i2cpHost);
if ( (_i2cpPort != null) && (_i2cpPort.trim().length() > 0) ) {
config.setProperty("i2cpPort", _i2cpPort);
} else {
config.setProperty("i2cpPort", "7654");
if (!_context.isRouterContext()) {
if (_i2cpHost != null)
config.setProperty("i2cpHost", _i2cpHost);
if ( (_i2cpPort != null) && (_i2cpPort.trim().length() > 0) ) {
config.setProperty("i2cpPort", _i2cpPort);
} else {
config.setProperty("i2cpPort", "7654");
}
}
if (_privKeyFile != null)
config.setProperty("privKeyFile", _privKeyFile);
@@ -1020,7 +1108,7 @@ public class IndexBean {
}
}
private String _(String key) {
protected String _(String key) {
return Messages._(key, _context);
}
}

View File

@@ -80,7 +80,7 @@
<label><%=intl._("Target")%>:</label>
<% } else { %>
<label><%=intl._("Access Point")%>:</label>
<% } %>
<% } /* streamrclient */ %>
</div>
<div id="portField" class="rowItem">
<label for="port" accesskey="P">
@@ -95,46 +95,41 @@
</label>
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
</div>
<% String otherInterface = "";
String clientInterface = editBean.getClientInterface(curTunnel);
if ("streamrclient".equals(tunnelType)) {
otherInterface = clientInterface;
} else { %>
<div id="reachField" class="rowItem">
<label for="reachableBy" accesskey="r">
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
</label>
<select id="reachableBy" name="reachableBy" title="Valid IP for Client Access" class="selectbox">
<% if (!("127.0.0.1".equals(clientInterface)) &&
!("0.0.0.0".equals(clientInterface)) &&
(clientInterface != null) &&
(clientInterface.trim().length() > 0)) {
otherInterface = clientInterface;
}
%><option value="127.0.0.1"<%=("127.0.0.1".equals(clientInterface) ? " selected=\"selected\"" : "")%>><%=intl._("Locally (127.0.0.1)")%></option>
<option value="0.0.0.0"<%=("0.0.0.0".equals(clientInterface) ? " selected=\"selected\"" : "")%>><%=intl._("Everyone (0.0.0.0)")%></option>
<option value="other"<%=(!("".equals(otherInterface)) ? " selected=\"selected\"" : "")%>><%=intl._("LAN Hosts (Please specify your LAN address)")%></option>
</select>
</div>
<% } // streamrclient %>
<div id="otherField" class="rowItem">
<label for="reachableByOther" accesskey="O">
<% if ("streamrclient".equals(tunnelType)) { %>
Host:
<% String vvv = otherInterface;
if (vvv == null || "".equals(vvv.trim())) {
<%
if ("streamrclient".equals(tunnelType)) {
out.write("Host:");
String targetHost = editBean.getTargetHost(curTunnel);
if (targetHost == null || "".equals(targetHost.trim())) {
out.write(" <font color=\"red\">(");
out.write(intl._("required"));
out.write(")</font>");
}
%>
<% } else { %>
<%=intl._("Other")%>(<span class="accessKey">O</span>):
<% } %>
%>
</label>
<input type="text" size="20" id="reachableByOther" name="reachableByOther" title="Alternative IP for Client Access" value="<%=otherInterface%>" class="freetext" />
</div>
<input type="text" size="20" id="targetHost" name="targetHost" title="Target Hostname or IP" value="<%=targetHost%>" class="freetext" />
<% } else { %>
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
</label>
<select id="reachableBy" name="reachableBy" title="IP for Client Access" class="selectbox">
<%
String clientInterface = editBean.getClientInterface(curTunnel);
for (String ifc : editBean.interfaceSet()) {
out.write("<option value=\"");
out.write(ifc);
out.write('\"');
if (ifc.equals(clientInterface))
out.write(" selected=\"selected\"");
out.write('>');
out.write(ifc);
out.write("</option>\n");
}
%>
</select>
<% } /* streamrclient */ %>
</div>
<div class="subdivider">
<hr />
</div>
@@ -286,19 +281,19 @@
<% } // !streamrclient %>
<div id="optionsField" class="rowItem">
<label><%=intl._("I2CP Options")%>:</label>
<label><%=intl._("Router I2CP Address")%>:</label>
</div>
<div id="optionsHostField" class="rowItem">
<label for="clientHost" accesskey="o">
<%=intl._("Host")%>(<span class="accessKey">o</span>):
</label>
<input type="text" id="clientHost" name="clientHost" size="20" title="I2CP Hostname or IP" value="<%=editBean.getI2CPHost(curTunnel)%>" class="freetext" />
<input type="text" id="clientHost" name="clientHost" size="20" title="I2CP Hostname or IP" value="<%=editBean.getI2CPHost(curTunnel)%>" class="freetext" <% if (editBean.isRouterContext()) { %> readonly="readonly" <% } %> />
</div>
<div id="optionsPortField" class="rowItem">
<label for="clientPort" accesskey="r">
<%=intl._("Port")%>(<span class="accessKey">r</span>):
</label>
<input type="text" id="port" name="clientport" size="20" title="I2CP Port Number" value="<%=editBean.getI2CPPort(curTunnel)%>" class="freetext" />
<input type="text" id="clientPort" name="clientport" size="20" title="I2CP Port Number" value="<%=editBean.getI2CPPort(curTunnel)%>" class="freetext" <% if (editBean.isRouterContext()) { %> readonly="readonly" <% } %> />
</div>
<% if (!"streamrclient".equals(tunnelType)) { // streamr client sends pings so it will never be idle %>
@@ -465,6 +460,18 @@
</div>
<% } // httpclient || connect || socks || socksirc %>
<% if ("httpclient".equals(tunnelType)) { %>
<div id="optionsField" class="rowItem">
<label><%=intl._("Jump URL List")%>:</label>
</div>
<div id="hostField" class="rowItem">
<textarea rows="2" style="height: 8em;" cols="60" id="hostField" name="jumpList" title="List of helper URLs to offer when a host is not found in your addressbook" wrap="off"><%=editBean.getJumpList(curTunnel)%></textarea>
</div>
<div class="subdivider">
<hr />
</div>
<% } // httpclient %>
<div id="customOptionsField" class="rowItem">
<label for="customOptions" accesskey="u">
<%=intl._("Custom options")%>(<span class="accessKey">u</span>):

View File

@@ -89,16 +89,14 @@
<label><%=intl._("Target")%>:</label>
<% } %>
</div>
<% if (!"streamrserver".equals(tunnelType)) { %>
<div id="hostField" class="rowItem">
<label for="targetHost" accesskey="H">
<% if ("streamrserver".equals(tunnelType)) { %>
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
<% } else { %>
<%=intl._("Host")%>(<span class="accessKey">H</span>):
<% } %>
</label>
<input type="text" size="20" id="targetHost" name="targetHost" title="Target Hostname or IP" value="<%=editBean.getTargetHost(curTunnel)%>" class="freetext" />
</div>
<% } /* !streamrserver */ %>
<div id="portField" class="rowItem">
<label for="targetPort" accesskey="P">
<%=intl._("Port")%>(<span class="accessKey">P</span>):
@@ -113,8 +111,7 @@
<input type="text" size="6" maxlength="5" id="targetPort" name="targetPort" title="Target Port Number" value="<%=editBean.getTargetPort(curTunnel)%>" class="freetext" />
</div>
<% if ("httpbidirserver".equals(tunnelType)) {
%>
<% if ("httpbidirserver".equals(tunnelType)) { %>
<div class="subdivider">
<hr />
</div>
@@ -134,32 +131,30 @@
</label>
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
</div>
<% String otherInterface = "";
String clientInterface = editBean.getClientInterface(curTunnel);
%>
<% } /* httpbidirserver */ %>
<% if ("httpbidirserver".equals(tunnelType) || "streamrserver".equals(tunnelType)) { %>
<div id="reachField" class="rowItem">
<label for="reachableBy" accesskey="r">
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
</label>
<select id="reachableBy" name="reachableBy" title="Valid IP for Client Access" class="selectbox">
<% if (!("127.0.0.1".equals(clientInterface)) &&
!("0.0.0.0".equals(clientInterface)) &&
(clientInterface != null) &&
(clientInterface.trim().length() > 0)) {
otherInterface = clientInterface;
}
%><option value="127.0.0.1"<%=("127.0.0.1".equals(clientInterface) ? " selected=\"selected\"" : "")%>><%=intl._("Locally (127.0.0.1)")%></option>
<option value="0.0.0.0"<%=("0.0.0.0".equals(clientInterface) ? " selected=\"selected\"" : "")%>><%=intl._("Everyone (0.0.0.0)")%></option>
<option value="other"<%=(!("".equals(otherInterface)) ? " selected=\"selected\"" : "")%>><%=intl._("LAN Hosts (Please specify your LAN address)")%></option>
<select id="reachableBy" name="reachableBy" title="IP for Client Access" class="selectbox">
<%
String clientInterface = editBean.getClientInterface(curTunnel);
for (String ifc : editBean.interfaceSet()) {
out.write("<option value=\"");
out.write(ifc);
out.write('\"');
if (ifc.equals(clientInterface))
out.write(" selected=\"selected\"");
out.write('>');
out.write(ifc);
out.write("</option>\n");
}
%>
</select>
</div>
<div id="otherField" class="rowItem">
<label for="reachableByOther" accesskey="O">
<%=intl._("Other")%>(<span class="accessKey">O</span>):
</label>
<input type="text" size="20" id="reachableByOther" name="reachableByOther" title="Alternative IP for Client Access" value="<%=otherInterface%>" class="freetext" />
</div>
<% } %>
<% } /* httpbidirserver || streamrserver */ %>
<div class="subdivider">
<hr />
</div>
@@ -302,22 +297,22 @@
<div class="subdivider">
<hr />
</div>
<% } // !streamrserver %>
<% } /* !streamrserver */ %>
<div id="optionsField" class="rowItem">
<label><%=intl._("I2CP Options")%>:</label>
<label><%=intl._("Router I2CP Address")%>:</label>
</div>
<div id="optionsHostField" class="rowItem">
<label for="clientHost" accesskey="o">
<%=intl._("Host")%>(<span class="accessKey">o</span>):
</label>
<input type="text" id="clientHost" name="clientHost" size="20" title="I2CP Hostname or IP" value="<%=editBean.getI2CPHost(curTunnel)%>" class="freetext" />
<input type="text" id="clientHost" name="clientHost" size="20" title="I2CP Hostname or IP" value="<%=editBean.getI2CPHost(curTunnel)%>" class="freetext" <% if (editBean.isRouterContext()) { %> readonly="readonly" <% } %> />
</div>
<div id="optionsPortField" class="rowItem">
<label for="clientPort" accesskey="r">
<%=intl._("Port")%>(<span class="accessKey">r</span>):
</label>
<input type="text" id="clientPort" name="clientport" size="20" title="I2CP Port Number" value="<%=editBean.getI2CPPort(curTunnel)%>" class="freetext" />
<input type="text" id="clientPort" name="clientport" size="20" title="I2CP Port Number" value="<%=editBean.getI2CPPort(curTunnel)%>" class="freetext" <% if (editBean.isRouterContext()) { %> readonly="readonly" <% } %> />
</div>
<div class="subdivider">
@@ -333,7 +328,7 @@
<label for="encrypt" accesskey="e">
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="encrypt" title="Encrypt LeaseSet"<%=(editBean.getEncrypt(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<input value="1" type="checkbox" id="startOnLoad" name="encrypt" title="ONLY clients with the encryption key will be able to connect"<%=(editBean.getEncrypt(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="portField" class="rowItem">
<label for="encrypt" accesskey="e">
@@ -359,19 +354,64 @@
</label>
</div>
<div id="portField" class="rowItem">
<label for="access" accesskey="s">
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="access" title="Enable Access List"<%=(editBean.getAccess(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<label><%=intl._("Disable")%></label>
<input value="0" type="radio" id="startOnLoad" name="accessMode" title="Allow all clients"<%=(editBean.getAccessMode(curTunnel).equals("0") ? " checked=\"checked\"" : "")%> class="tickbox" />
<label><%=intl._("Whitelist")%></label>
<input value="1" type="radio" id="startOnLoad" name="accessMode" title="Allow listed clients only"<%=(editBean.getAccessMode(curTunnel).equals("1") ? " checked=\"checked\"" : "")%> class="tickbox" />
<label><%=intl._("Blacklist")%></label>
<input value="2" type="radio" id="startOnLoad" name="accessMode" title="Reject listed clients"<%=(editBean.getAccessMode(curTunnel).equals("2") ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="hostField" class="rowItem">
<label for="accessList" accesskey="s">
<%=intl._("Access List")%>:
</label>
<textarea rows="2" style="height: 4em;" cols="60" id="hostField" name="accessList" title="Access List" wrap="off"><%=editBean.getAccessList(curTunnel)%></textarea>
<span class="comment"><%=intl._("(Restrict to these clients only)")%></span>
<textarea rows="2" style="height: 8em;" cols="60" id="hostField" name="accessList" title="Access List" wrap="off"><%=editBean.getAccessList(curTunnel)%></textarea>
</div>
<div class="subdivider">
<hr />
</div>
<div class="rowItem">
<div id="optionsField" class="rowItem">
<label><%=intl._("Inbound connection limits (0 to disable)")%><br><%=intl._("Per client")%>:</label>
</div>
<div id="portField" class="rowItem">
<label><%=intl._("Per minute")%>:</label>
<input type="text" id="port" name="limitMinute" value="<%=editBean.getLimitMinute(curTunnel)%>" class="freetext" />
</div>
<div id="portField" class="rowItem">
<label><%=intl._("Per hour")%>:</label>
<input type="text" id="port" name="limitHour" value="<%=editBean.getLimitHour(curTunnel)%>" class="freetext" />
</div>
<div id="portField" class="rowItem">
<label><%=intl._("Per day")%>:</label>
<input type="text" id="port" name="limitDay" value="<%=editBean.getLimitDay(curTunnel)%>" class="freetext" />
</div>
</div>
<div class="rowItem">
<div id="optionsField" class="rowItem">
<label><%=intl._("Total")%>:</label>
</div>
<div id="portField" class="rowItem">
<input type="text" id="port" name="totalMinute" value="<%=editBean.getTotalMinute(curTunnel)%>" class="freetext" />
</div>
<div id="portField" class="rowItem">
<input type="text" id="port" name="totalHour" value="<%=editBean.getTotalHour(curTunnel)%>" class="freetext" />
</div>
<div id="portField" class="rowItem">
<input type="text" id="port" name="totalDay" value="<%=editBean.getTotalDay(curTunnel)%>" class="freetext" />
</div>
</div>
<div class="rowItem">
<div id="optionsField" class="rowItem">
<label><%=intl._("Max concurrent connections (0 to disable)")%>:</label>
</div>
<div id="portField" class="rowItem">
<input type="text" id="port" name="maxStreams" value="<%=editBean.getMaxStreams(curTunnel)%>" class="freetext" />
</div>
</div>
<div class="subdivider">
<hr />
</div>

View File

@@ -95,7 +95,7 @@
<label><%=intl._("Points at")%>:</label>
<span class="text">
<%
if ("httpserver".equals(indexBean.getInternalType(curServer))) {
if (indexBean.isServerTargetLinkValid(curServer)) {
%>
<a href="http://<%=indexBean.getServerTarget(curServer)%>/" title="Test HTTP server, bypassing I2P"><%=indexBean.getServerTarget(curServer)%></a>
<%
@@ -213,7 +213,18 @@
</div>
<div class="portField rowItem">
<label><%=intl._("Port")%>:</label>
<span class="text"><%=indexBean.getClientPort(curClient)%></span>
<span class="text">
<%
String cPort= indexBean.getClientPort(curClient);
if ("".equals(cPort)) {
out.write("<font color=\"red\">");
out.write(intl._("Port not set"));
out.write("</font>");
} else {
out.write(cPort);
}
%>
</span>
</div>
<div class="typeField rowItem">
<label><%=intl._("Type")%>:</label>
@@ -221,7 +232,19 @@
</div>
<div class="interfaceField rowItem">
<label><%=intl._("Interface")%>:</label>
<span class="text"><%=indexBean.getClientInterface(curClient)%></span>
<span class="text">
<%
/* should only happen for streamr client */
String cHost= indexBean.getClientInterface(curClient);
if ("".equals(cHost)) {
out.write("<font color=\"red\">");
out.write(intl._("Host not set"));
out.write("</font>");
} else {
out.write(cHost);
}
%>
</span>
</div>
<div class="statusField rowItem">
<label><%=intl._("Status")%>:</label>

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-12-17 15:04+0000\n"
"POT-Creation-Date: 2011-01-20 19:26+0000\n"
"PO-Revision-Date: 2010-06-15 14:09+0100\n"
"Last-Translator: duck <duck@mail.i2p>\n"
"Language-Team: duck <duck@mail.i2p>, monkeybrains <monkeybrains@mail.i2p>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Dutch\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:475
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:474
#, java-format
msgid ""
"To visit the destination in your host database, click <a href=\"{0}\">here</"
@@ -28,13 +28,18 @@ msgstr ""
"\">hier</a>. Om de conflicterende adreshelper destination te bezoeken, klik "
"<a href=\"{1}\">hier</a>."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:932
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:931
msgid ""
"Click a link below to look for an address helper by using a \"jump\" service:"
msgstr ""
"Klik op een onderstaande link om te zoeken naar een adreshelper via een "
"\"jump\" service:"
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:326
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:336
msgid "internal"
msgstr "intern"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:170
msgid ""
"Invalid form submission, probably because you used the 'back' or 'reload' "
@@ -109,6 +114,16 @@ msgstr "Streamr server"
msgid "HTTP bidir"
msgstr "HTTP bidir"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:508
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:290
msgid "Host not set"
msgstr "Host niet opgegeven"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:512
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:272
msgid "Port not set"
msgstr "Poort niet opgegeven"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:73
msgid "I2P Tunnel Manager - Edit Client Tunnel"
msgstr "I2P Tunnel Manager - Bewerk Client Tunnel"
@@ -133,14 +148,14 @@ msgstr "Naam"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:116
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:116
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:246
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:270
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:279
msgid "Type"
msgstr "Type"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:120
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:120
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:226
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:367
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:386
msgid "Description"
msgstr "Omschrijving"
@@ -151,66 +166,45 @@ msgstr "Doel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:130
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:132
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:167
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:162
msgid "Access Point"
msgstr "Toegangspunt"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:137
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:179
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:207
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:157
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:172
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:228
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:150
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:192
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:153
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:167
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:213
msgid "required"
msgstr "vereist"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:150
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:142
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:183
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:159
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:178
msgid "Reachable by"
msgstr "Bereikbaar voor"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:162
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:195
msgid "Locally (127.0.0.1)"
msgstr "Lokaal (127.0.0.1)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:166
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:199
msgid "Everyone (0.0.0.0)"
msgstr "Iedereen (0.0.0.0)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:170
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:203
msgid "LAN Hosts (Please specify your LAN address)"
msgstr "LAN Hosts (Specificeer je LAN adres)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:186
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:205
msgid "Other"
msgstr "Anders"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:195
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:180
msgid "Outproxies"
msgstr "Uitgaande proxies"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:202
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:187
msgid "Tunnel Destination"
msgstr "Tunnel Destinations"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:214
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:199
msgid "name or destination"
msgstr "naam of destination"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:217
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:202
msgid "b32 not recommended"
msgstr "b32 niet aanbevolen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:223
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:208
msgid "Shared Client"
msgstr "Gedeelde Client"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:212
msgid ""
"(Share tunnels with other clients and irc/httpclients? Change requires "
"restart of client proxy)"
@@ -218,22 +212,22 @@ msgstr ""
"(Deel tunnels met andere clients en irc/httpclients? Wijziging vereist "
"herstart van de client proxy)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:231
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:216
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:124
msgid "Auto Start"
msgstr "Auto Start"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:235
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:220
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:128
msgid "(Check the Box for 'YES')"
msgstr "(Markeer de Box voor 'JA')"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:237
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:258
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:222
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:243
msgid "Advanced networking options"
msgstr "Geavanceerde netwerk opties"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:224
msgid ""
"(NOTE: when this client proxy is configured to share tunnels, then these "
"options are for all the shared proxy clients!)"
@@ -241,93 +235,93 @@ msgstr ""
"(OPMERKING: wanneer deze client proxy is geconfigureerd om tunnels te delen, "
"dan zijn deze opties van toepassing voor alle gedeelde proxy clients!)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:241
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:260
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:226
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:245
msgid "Tunnel Options"
msgstr "Tunnel Opties"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:243
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:262
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:228
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:247
msgid "Length"
msgstr "Lengte"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:250
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:269
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:235
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:254
msgid "0 hop tunnel (low anonymity, low latency)"
msgstr "0 hop tunnel (lage anonimiteit, weinig vertraging)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:254
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:273
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:258
msgid "1 hop tunnel (medium anonymity, medium latency)"
msgstr "1 hop tunnel (gemiddelde anonimiteit, gemiddelde vertraging)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:258
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:277
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:243
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:262
msgid "2 hop tunnel (high anonymity, high latency)"
msgstr "2 hop tunnel (hoge anonimiteit, hoge vertraging)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:262
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:247
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:266
msgid "3 hop tunnel (very high anonymity, poor performance)"
msgstr "3 hop tunnel (zeer hoge anonimiteit, slechte prestatie)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:271
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:290
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:256
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:275
msgid "hop tunnel (very poor performance)"
msgstr "hop tunnel (zeer slechte prestatie)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:276
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:295
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:261
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:280
msgid "Variance"
msgstr "Variantie"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:283
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:302
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:268
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:287
msgid "0 hop variance (no randomisation, consistant performance)"
msgstr "0 hop variantie (geen randomisatie, consistente prestatie)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:287
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:306
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:272
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:291
msgid ""
"+ 0-1 hop variance (medium additive randomisation, subtractive performance)"
msgstr ""
"+ 0-1 hop variantie (gemiddeld toegevoegde randomisatie, minder prestatie)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:291
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:310
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:276
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:295
msgid ""
"+ 0-2 hop variance (high additive randomisation, subtractive performance)"
msgstr "+ 0-2 hop variantie (hoge toegevoegde randomisatie, minder prestatie)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:295
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:314
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:280
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:299
msgid "+/- 0-1 hop variance (standard randomisation, standard performance)"
msgstr "+/- 0-1 hop variantie (standaard randomisatie, standaard prestatie)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:299
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:318
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:284
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:303
msgid "+/- 0-2 hop variance (not recommended)"
msgstr "+/- 0-2 hop variantie (niet aanbevolen)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:311
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:330
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:296
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:315
msgid "hop variance"
msgstr "hop variantie"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:316
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:335
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:301
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:320
msgid "Count"
msgstr "Aantal"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:323
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:342
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:308
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:327
msgid "1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)"
msgstr ""
"1 inkomende, 1 uitgaande tunnel (laag bandbreedte gebruik, minder "
"betrouwbaar)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:327
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:346
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:312
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:331
msgid ""
"2 inbound, 2 outbound tunnels (standard bandwidth usage, standard "
"reliability)"
@@ -335,185 +329,189 @@ msgstr ""
"2 inkomende, 2 uitgaande tunnels (standaard bandbreedte gebruik, standaard "
"betrouwbaarheid)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:331
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:350
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:316
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:335
msgid ""
"3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)"
msgstr ""
"3 inkomende, 3 uitgaande tunnels (hoge bandbreedte gebruik, hogere "
"betrouwbaarheid)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:340
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:359
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:325
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:344
msgid "tunnels"
msgstr "tunnels"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:345
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:364
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:330
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:349
msgid "Backup Count"
msgstr "Backup Aantal"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:352
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:371
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:337
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:356
msgid "0 backup tunnels (0 redundancy, no added resource usage)"
msgstr "0 backup tunnels (0 redundantie, geen additionele bronnen gebruikt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:356
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:375
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:341
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:360
msgid "1 backup tunnel each direction (low redundancy, low resource usage)"
msgstr ""
"1 backup tunnel in beide richting (lage redundantie, lage aantal bronnen "
"gebruikt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:360
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:379
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:345
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:364
msgid ""
"2 backup tunnels each direction (medium redundancy, medium resource usage)"
msgstr ""
"2 backup tunnels in beide richting (gemiddelde redundantie, gemiddeld aantal "
"bronnen gebruikt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:364
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:383
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:349
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:368
msgid "3 backup tunnels each direction (high redundancy, high resource usage)"
msgstr ""
"3 backup tunnels in beide richting (hoge redundantie, hoog aantal bronnen "
"gebruikt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:373
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:392
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:358
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:377
msgid "backup tunnels"
msgstr "backup tunnels"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:380
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:399
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:365
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:384
msgid "Profile"
msgstr "Profiel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:387
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:406
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:372
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:391
msgid "interactive connection"
msgstr "interactieve connectie"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:391
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:410
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:376
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:395
msgid "bulk connection (downloads/websites/BT)"
msgstr "bulk connection (downloads/websites/BT)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:393
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:378
msgid "Delay Connect"
msgstr "Vertraagde Connectie"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:397
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:382
msgid "for request/response connections"
msgstr "voor request/response connecties"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:401
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:414
msgid "I2CP Options"
msgstr "I2CP Opties"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:386
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:399
msgid "Router I2CP Address"
msgstr "Router I2CP Adres"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:403
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:146
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:416
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:388
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:142
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:401
msgid "Host"
msgstr "Host"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:407
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:152
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:420
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:396
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:148
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:409
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:244
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:266
msgid "Port"
msgstr "Poort"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:413
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:452
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:406
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:479
msgid "Reduce tunnel quantity when idle"
msgstr "Verminder tunnel aantal wanneer in rust"
msgstr "Verminder tunnel aantal in ruststand"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:415
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:429
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:437
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:449
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:459
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:479
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:493
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:426
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:442
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:454
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:408
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:422
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:430
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:442
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:452
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:472
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:486
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:419
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:481
msgid "Enable"
msgstr "Ingeschakeld"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:419
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:458
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:412
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:485
msgid "Reduced tunnel count"
msgstr "Verminder tunnel aantal"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:423
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:443
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:462
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:416
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:436
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:489
msgid "Idle minutes"
msgstr "Rust minuten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:427
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:420
msgid "Close tunnels when idle"
msgstr "Sluit tunnels wanneer in rust"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:433
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:426
msgid "New Keys on Reopen"
msgstr "Nieuwe Sleutels bij Heropenen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:441
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:434
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:435
msgid "Disable"
msgstr "Uitgeschakeld"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:447
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:440
msgid "Delay tunnel open until required"
msgstr "Vertraag tunnel opening totdat het nodig is"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:457
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:450
msgid "Persistent private key"
msgstr "Persistente private sleutel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:463
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:456
msgid "File"
msgstr "Bestand"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:467
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:235
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:460
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:220
msgid "Local destination"
msgstr "Lokale destination"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:471
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:464
msgid "(if known)"
msgstr "(indien bekend)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:477
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:470
msgid "Local Authorization"
msgstr "Lokale Autorisatie"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:483
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:497
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:476
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:490
msgid "Username"
msgstr "Gebruikersnaam"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:487
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:501
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:480
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:494
msgid "Password"
msgstr "Wachtwoord"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:491
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:484
msgid "Outproxy Authorization"
msgstr "Uitgaande Proxy Autorisatie"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:507
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:498
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:502
msgid "Jump URL List"
msgstr "Spring URL Lijst"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:508
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:525
msgid "Custom options"
msgstr "Aangepaste opties"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:511
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:502
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:512
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:529
msgid ""
"NOTE: If tunnel is currently running, most changes will not take effect "
"until tunnel is stopped and restarted."
@@ -521,18 +519,18 @@ msgstr ""
"OPMERKING: Indien de tunnel op dit moment draait, zullen de meeste "
"wijzigingen pas effect hebben na het stoppen en herstarten van de tunnel."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:513
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:504
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:514
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:531
msgid "Cancel"
msgstr "Annuleer"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:517
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:508
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:518
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:535
msgid "Delete"
msgstr "Verwijder"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:519
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:510
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:520
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:537
msgid "Save"
msgstr "Opslaan"
@@ -548,92 +546,124 @@ msgstr "Bewerk server instellingen"
msgid "New server settings"
msgstr "Nieuwe server instellingen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:214
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:199
msgid "Website name"
msgstr "Website naam"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:218
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:203
msgid "(leave blank for outproxies)"
msgstr "(leeg laten voor uitgaande proxies)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:223
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:208
msgid "Private key file"
msgstr "Private sleutel bestand"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:245
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:230
msgid "Add to local addressbook"
msgstr "Toevoegen aan lokaal adresboek"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:252
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:237
msgid "Hostname Signature"
msgstr "Hostnaam Handtekening"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:424
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:417
msgid "Encrypt Leaseset"
msgstr "Versleutel Leaseset"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:430
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:423
msgid "Encryption Key"
msgstr "Encryptie Sleutel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:434
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:427
msgid "Generate New Key"
msgstr "Genereer Nieuwe Sleutel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:436
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:429
msgid "Generate"
msgstr "Genereer"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:438
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:496
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:431
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:523
msgid "(Tunnel must be stopped first)"
msgstr "(Tunnel moet eerst gestopt worden)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:440
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:433
msgid "Restricted Access List"
msgstr "Beperkte Toegangs Lijst"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:446
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:439
msgid "Whitelist"
msgstr "Wittelijst"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:443
msgid "Blacklist"
msgstr "Zwartelijst"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:447
msgid "Access List"
msgstr "Toegangs Lijst"
msgstr "Toegangslijst"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:450
msgid "(Restrict to these clients only)"
msgstr "(Beperkt tot slechts deze clients)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:451
msgid "Inbound connection limits (0 to disable)"
msgstr "Inkomende connectie limieten (0 om uit te schakelen)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:466
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:453
msgid "Per client"
msgstr "Per client"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:455
msgid "Per minute"
msgstr "Per minuut"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:459
msgid "Per hour"
msgstr "Per uur"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:463
msgid "Per day"
msgstr "Per dag"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:467
msgid "Total"
msgstr "Totaal"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:475
msgid "Max concurrent connections (0 to disable)"
msgstr "Maximum gelijktijdige connecties (0 om uit te schakelen)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:493
msgid "New Certificate type"
msgstr "Nieuw Certificaat type"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:468
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:495
msgid "None"
msgstr "Geen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:472
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:499
msgid "Hashcash (effort)"
msgstr "Hashcash (effort)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:478
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:505
msgid "Hashcash Calc Time"
msgstr "Hashcash Reken Tijd"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:480
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:507
msgid "Estimate"
msgstr "Inschatten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:482
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:509
msgid "Hidden"
msgstr "Verborgen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:486
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:513
msgid "Signed (signed by)"
msgstr "Ondertekend (ondertekend door)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:492
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:519
msgid "Modify Certificate"
msgstr "Wijzig Certificaat"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:494
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:521
msgid "Modify"
msgstr "Wijzig"
@@ -683,7 +713,7 @@ msgstr "Preview"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:113
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:177
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:250
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:278
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:297
msgid "Status"
msgstr "Status"
@@ -696,30 +726,30 @@ msgid "No Preview"
msgstr "Geen Preview"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:184
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:285
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:304
msgid "Starting..."
msgstr "Starten..."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:191
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:205
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:292
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:306
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:320
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:311
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:325
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:339
msgid "Stop"
msgstr "Stop"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:198
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:313
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:332
msgid "Running"
msgstr "Draait"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:212
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:327
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:346
msgid "Stopped"
msgstr "Gestopt"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:219
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:334
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:353
msgid "Start"
msgstr "Start"
@@ -728,12 +758,12 @@ msgid "New server tunnel"
msgstr "Nieuwe server tunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:236
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:377
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:396
msgid "Standard"
msgstr "Standaard"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:238
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:379
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:398
msgid "Create"
msgstr "Creëer"
@@ -742,26 +772,26 @@ msgid "I2P Client Tunnels"
msgstr "I2P Client Tunnels"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:248
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:274
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:283
msgid "Interface"
msgstr "Interface"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:299
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:318
msgid "Standby"
msgstr "Stand-by"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:344
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:363
msgid "Outproxy"
msgstr "Uitgaande proxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:348
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:367
msgid "Destination"
msgstr "Destination"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:362
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:381
msgid "none"
msgstr "geen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:375
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:394
msgid "New client tunnel"
msgstr "Nieuwe client tunnel"

View File

@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-12-13 19:43+0000\n"
"PO-Revision-Date: 2010-12-14 00:54+0500\n"
"POT-Creation-Date: 2011-01-17 18:54+0000\n"
"PO-Revision-Date: 2011-01-18 00:34+0500\n"
"Last-Translator: Hidden Z <hiddenz@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"Language: \n"
@@ -18,15 +18,20 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Russian\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:475
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:474
#, java-format
msgid "To visit the destination in your host database, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, click <a href=\"{1}\">here</a>."
msgstr "Для перехода по ссылке из локальной адресной книги, нажмите <a href=\"{0}\">здесь</a>. Для перехода по новой addresshelper-ссылке, нажмите <a href=\"{1}\">здесь</a>."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:932
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:931
msgid "Click a link below to look for an address helper by using a \"jump\" service:"
msgstr "Jump-сервисы, которые, возможно, знают нужную Вам addresshelper-ссылку:"
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:326
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:336
msgid "internal"
msgstr "внутренний"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:170
msgid "Invalid form submission, probably because you used the 'back' or 'reload' button on your browser. Please resubmit."
msgstr "Неправильно переданная форма, возможно вы использовали действие браузера \"назад\" или \"обновить\". Пожалуйста повторите попытку."
@@ -97,6 +102,15 @@ msgstr "Streamr-сервер"
msgid "HTTP bidir"
msgstr "HTTP bidir (экспериментальный двунаправленный режим, инструкцию спрашивайте у sponge)"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:508
msgid "Host not set"
msgstr "Хост не задан"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:512
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:272
msgid "Port not set"
msgstr "Порт не задан"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:73
msgid "I2P Tunnel Manager - Edit Client Tunnel"
msgstr "Менеджер Туннелей I2P — Редактирование Клиентского Туннеля"
@@ -121,14 +135,14 @@ msgstr "Название"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:116
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:116
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:246
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:270
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:279
msgid "Type"
msgstr "Тип"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:120
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:120
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:226
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:367
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:386
msgid "Description"
msgstr "Описание"
@@ -139,357 +153,340 @@ msgstr "Точка доступа"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:130
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:132
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:167
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:162
msgid "Access Point"
msgstr "Точка доступа"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:137
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:179
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:207
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:157
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:172
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:228
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:150
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:192
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:153
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:167
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:213
msgid "required"
msgstr "*"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:150
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:142
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:183
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:159
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:178
msgid "Reachable by"
msgstr "Кому будет доступно (Сетевой интерфейс)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:162
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:195
msgid "Locally (127.0.0.1)"
msgstr "Только в пределах этого компьютера (127.0.0.1)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:166
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:199
msgid "Everyone (0.0.0.0)"
msgstr "Всем (0.0.0.0)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:170
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:203
msgid "LAN Hosts (Please specify your LAN address)"
msgstr "Только из локальной сети (Введите свой LAN-адрес)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:186
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:205
msgid "Other"
msgstr "Адрес сетевого интерфейса"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:195
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:180
msgid "Outproxies"
msgstr "Список outproxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:202
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:187
msgid "Tunnel Destination"
msgstr "Адрес назначения туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:214
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:199
msgid "name or destination"
msgstr "имя или адрес"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:217
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:202
msgid "b32 not recommended"
msgstr "b32 не рекомендуется"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:223
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:208
msgid "Shared Client"
msgstr "Коллективный клиент"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:212
msgid "(Share tunnels with other clients and irc/httpclients? Change requires restart of client proxy)"
msgstr "(Использовать туннели коллективно/совместно с другими прокси-клиентами? Изменение настройки потребует перезапуска туннеля)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:231
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:216
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:124
msgid "Auto Start"
msgstr "Автозапуск"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:235
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:220
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:128
msgid "(Check the Box for 'YES')"
msgstr "(поставьте галочку для включения)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:237
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:258
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:222
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:243
msgid "Advanced networking options"
msgstr "Расширенные сетевые настройки"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:224
msgid "(NOTE: when this client proxy is configured to share tunnels, then these options are for all the shared proxy clients!)"
msgstr "(ПРИМЕЧАНИЕ: при коллективном использовании туннелей эти опции будут применяться ко всем коллективным прокси-клиентам!)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:241
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:260
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:226
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:245
msgid "Tunnel Options"
msgstr "Параметры туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:243
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:262
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:228
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:247
msgid "Length"
msgstr "Длина"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:250
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:269
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:235
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:254
msgid "0 hop tunnel (low anonymity, low latency)"
msgstr "0 хопов (низкая анонимность, малые задержки)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:254
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:273
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:258
msgid "1 hop tunnel (medium anonymity, medium latency)"
msgstr "1 хоп (умеренная анонимность, умеренные задержки)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:258
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:277
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:243
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:262
msgid "2 hop tunnel (high anonymity, high latency)"
msgstr "2 хопа (высокая анонимность, высокие задержки)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:262
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:247
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:266
msgid "3 hop tunnel (very high anonymity, poor performance)"
msgstr "3 хопа (очень высокая анонимность, низкая производительность)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:271
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:290
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:256
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:275
msgid "hop tunnel (very poor performance)"
msgstr "хопов (очень низкая производительность)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:276
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:295
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:261
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:280
msgid "Variance"
msgstr "Разброс"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:283
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:302
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:268
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:287
msgid "0 hop variance (no randomisation, consistant performance)"
msgstr "нулевой разброс (без рандомизации, фиксированная производительность)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:287
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:306
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:272
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:291
msgid "+ 0-1 hop variance (medium additive randomisation, subtractive performance)"
msgstr "+ 0-1 разброс (умеренно повышенная рандомизация, пониженная производительность)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:291
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:310
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:276
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:295
msgid "+ 0-2 hop variance (high additive randomisation, subtractive performance)"
msgstr "+ 0-2 разброс (сильно повышенная рандомизация, пониженная производительность)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:295
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:314
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:280
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:299
msgid "+/- 0-1 hop variance (standard randomisation, standard performance)"
msgstr "+/- 0-1 разброс (стандартная рандомизация, стандартная производительность)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:299
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:318
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:284
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:303
msgid "+/- 0-2 hop variance (not recommended)"
msgstr "+/- 0-2 разброс (не рекомендуется)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:311
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:330
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:296
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:315
msgid "hop variance"
msgstr "разброс"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:316
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:335
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:301
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:320
msgid "Count"
msgstr "Количество"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:323
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:342
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:308
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:327
msgid "1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)"
msgstr "1 входящий, 1 исходящий туннель (низкая пропускная способность, низкая надежность) "
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:327
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:346
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:312
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:331
msgid "2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)"
msgstr "2 входящих, 2 исходящих туннеля (стандартная пропускная способность, стандартная надежность)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:331
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:350
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:316
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:335
msgid "3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)"
msgstr "3 входящих, 3 исходящих туннеля (высокая пропускная способность, высокая надежность)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:340
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:359
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:325
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:344
msgid "tunnels"
msgstr "туннелей"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:345
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:364
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:330
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:349
msgid "Backup Count"
msgstr "Резервное количество"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:352
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:371
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:337
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:356
msgid "0 backup tunnels (0 redundancy, no added resource usage)"
msgstr "без резервных туннелей (отсутствие избыточности, отсутствие дополнительной нагрузки на систему)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:356
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:375
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:341
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:360
msgid "1 backup tunnel each direction (low redundancy, low resource usage)"
msgstr "1 резервный туннель в каждом направлении (низкая избыточность, низкая нагрузка на систему)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:360
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:379
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:345
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:364
msgid "2 backup tunnels each direction (medium redundancy, medium resource usage)"
msgstr "2 резервных туннеля в каждом направлении (умеренная избыточность, умеренная нагрузка на систему)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:364
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:383
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:349
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:368
msgid "3 backup tunnels each direction (high redundancy, high resource usage)"
msgstr "3 резервных туннеля в каждом направлении (высокая избыточность, высокая нагрузка на систему)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:373
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:392
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:358
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:377
msgid "backup tunnels"
msgstr "резервных туннелей"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:380
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:399
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:365
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:384
msgid "Profile"
msgstr "Режим"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:387
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:406
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:372
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:391
msgid "interactive connection"
msgstr "оптимизировать для малых задержек (irc)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:391
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:410
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:376
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:395
msgid "bulk connection (downloads/websites/BT)"
msgstr "оптимизировать для большого обьема (www/bittorrent)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:393
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:378
msgid "Delay Connect"
msgstr "Задержка соединения"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:397
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:382
msgid "for request/response connections"
msgstr "оптимизация для соединений, начинающихся с запроса клиента/ответа сервера"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:401
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:414
msgid "I2CP Options"
msgstr "Параметры I2CP"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:386
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:399
msgid "Router I2CP Address"
msgstr "I2CP Адрес Роутера"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:403
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:146
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:416
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:388
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:142
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:401
msgid "Host"
msgstr "Адрес"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:407
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:152
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:420
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:396
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:148
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:409
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:244
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:266
msgid "Port"
msgstr "Порт"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:413
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:452
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:406
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:479
msgid "Reduce tunnel quantity when idle"
msgstr "Снижать количество туннелей при простое"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:415
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:429
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:437
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:449
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:459
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:479
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:493
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:426
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:442
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:454
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:408
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:422
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:430
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:442
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:452
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:472
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:486
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:419
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:481
msgid "Enable"
msgstr "Включить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:419
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:458
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:412
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:485
msgid "Reduced tunnel count"
msgstr "Количество туннелей"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:423
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:443
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:462
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:416
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:436
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:489
msgid "Idle minutes"
msgstr "Минут простоя"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:427
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:420
msgid "Close tunnels when idle"
msgstr "Закрыть туннели при простое"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:433
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:426
msgid "New Keys on Reopen"
msgstr "Генерировать новый ключ при переоткрытии"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:441
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:434
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:435
msgid "Disable"
msgstr "Выключить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:447
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:440
msgid "Delay tunnel open until required"
msgstr "Отложить запуск до первого запроса"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:457
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:450
msgid "Persistent private key"
msgstr "Постоянный секретный ключ"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:463
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:456
msgid "File"
msgstr "Файл"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:467
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:235
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:460
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:220
msgid "Local destination"
msgstr "Локальный адрес назначения"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:471
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:464
msgid "(if known)"
msgstr "(если известен)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:477
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:470
msgid "Local Authorization"
msgstr "Локальная авторизация"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:483
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:497
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:476
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:490
msgid "Username"
msgstr "Имя пользователя"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:487
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:501
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:480
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:494
msgid "Password"
msgstr "Пароль"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:491
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:484
msgid "Outproxy Authorization"
msgstr "Авторизация outproxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:507
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:498
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:502
msgid "Jump URL List"
msgstr "Список адресов jump-сервисов"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:508
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:525
msgid "Custom options"
msgstr "Дополнительные параметры"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:511
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:502
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:512
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:529
msgid "NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted."
msgstr "ПРИМЕЧАНИЕ: для вступления в силу измененных настроек потребуется остановка и перезапуск туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:513
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:504
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:514
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:531
msgid "Cancel"
msgstr "Отмена"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:517
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:508
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:518
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:535
msgid "Delete"
msgstr "Удалить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:519
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:510
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:520
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:537
msgid "Save"
msgstr "Сохранить"
@@ -505,92 +502,124 @@ msgstr "Редактирование настроек серверного ту
msgid "New server settings"
msgstr "Настройки нового серверного туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:214
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:199
msgid "Website name"
msgstr "Имя веб-сайта"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:218
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:203
msgid "(leave blank for outproxies)"
msgstr "(не заполнять для outproxy)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:223
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:208
msgid "Private key file"
msgstr "Файл секретного ключа"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:245
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:230
msgid "Add to local addressbook"
msgstr "Добавить в локальную адресную книгу"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:252
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:237
msgid "Hostname Signature"
msgstr "Подпись хоста"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:424
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:417
msgid "Encrypt Leaseset"
msgstr "Шифровать LeaseSet"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:430
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:423
msgid "Encryption Key"
msgstr "Ключ шифрования"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:434
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:427
msgid "Generate New Key"
msgstr "Сгенерировать новый ключ"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:436
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:429
msgid "Generate"
msgstr "Сгенерировать"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:438
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:496
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:431
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:523
msgid "(Tunnel must be stopped first)"
msgstr "(Туннель перед этим следует остановить)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:440
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:433
msgid "Restricted Access List"
msgstr "Ограниченный доступ"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:446
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:439
msgid "Whitelist"
msgstr "Белый список"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:443
msgid "Blacklist"
msgstr "Чёрный список"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:447
msgid "Access List"
msgstr "Список доступа"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:450
msgid "(Restrict to these clients only)"
msgstr "(Разрешить доступ только перечисленным клиентам)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:451
msgid "Inbound connection limits (0 to disable)"
msgstr "Ограничение входящих соединений (0 для отключения)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:466
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:453
msgid "Per client"
msgstr "На клиента"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:455
msgid "Per minute"
msgstr "В минуту"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:459
msgid "Per hour"
msgstr "В час"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:463
msgid "Per day"
msgstr "В сутки"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:467
msgid "Total"
msgstr "Всего"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:475
msgid "Max concurrent connections (0 to disable)"
msgstr "Максимум одновременных соединений (0 для отключения)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:493
msgid "New Certificate type"
msgstr "Создать новый сертификат. Тип"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:468
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:495
msgid "None"
msgstr "Без"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:472
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:499
msgid "Hashcash (effort)"
msgstr "Hashcash (экспериментальный)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:478
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:505
msgid "Hashcash Calc Time"
msgstr "Время генерации hashcash-сертификата"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:480
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:507
msgid "Estimate"
msgstr "Прогноз"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:482
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:509
msgid "Hidden"
msgstr "Скрытый"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:486
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:513
msgid "Signed (signed by)"
msgstr "Подписанный (указать кем подписан)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:492
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:519
msgid "Modify Certificate"
msgstr "Изменить сертификат"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:494
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:521
msgid "Modify"
msgstr "Изменить"
@@ -640,7 +669,7 @@ msgstr "Предпросмотр"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:113
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:177
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:250
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:278
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:297
msgid "Status"
msgstr "Состояние"
@@ -653,30 +682,30 @@ msgid "No Preview"
msgstr "Предпросмотр недоступен"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:184
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:285
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:304
msgid "Starting..."
msgstr "Запускается..."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:191
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:205
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:292
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:306
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:320
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:311
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:325
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:339
msgid "Stop"
msgstr "Остановить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:198
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:313
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:332
msgid "Running"
msgstr "Запущен"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:212
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:327
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:346
msgid "Stopped"
msgstr "Остановлен"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:219
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:334
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:353
msgid "Start"
msgstr "Запустить"
@@ -685,12 +714,12 @@ msgid "New server tunnel"
msgstr "Новый серверный туннель"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:236
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:377
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:396
msgid "Standard"
msgstr "Стандартный"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:238
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:379
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:398
msgid "Create"
msgstr "Создать"
@@ -699,30 +728,48 @@ msgid "I2P Client Tunnels"
msgstr "Клиентские I2P туннели"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:248
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:274
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:283
msgid "Interface"
msgstr "Сетевой интерфейс"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:299
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:318
msgid "Standby"
msgstr "Режим ожидания"
# This term intentionally left in English
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:344
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:363
msgid "Outproxy"
msgstr "Outproxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:348
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:367
msgid "Destination"
msgstr "Адрес назначения"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:362
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:381
msgid "none"
msgstr "нет"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:375
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:394
msgid "New client tunnel"
msgstr "Новый клиентский туннель"
#~ msgid "Locally (127.0.0.1)"
#~ msgstr "Только в пределах этого компьютера (127.0.0.1)"
#~ msgid "Everyone (0.0.0.0)"
#~ msgstr "Всем (0.0.0.0)"
#~ msgid "LAN Hosts (Please specify your LAN address)"
#~ msgstr "Только из локальной сети (Введите свой LAN-адрес)"
#~ msgid "Other"
#~ msgstr "Адрес сетевого интерфейса"
#~ msgid "I2CP Options"
#~ msgstr "Параметры I2CP"
#~ msgid "(Restrict to these clients only)"
#~ msgstr "(Разрешить доступ только перечисленным клиентам)"
#~ msgid "Unimplemented"
#~ msgstr "не реализовано"

View File

@@ -0,0 +1,809 @@
// ========================================================================
// $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $
// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
package org.mortbay.http.handler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.List;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
import org.mortbay.http.HttpException;
import org.mortbay.http.HttpFields;
import org.mortbay.http.HttpRequest;
import org.mortbay.http.HttpResponse;
import org.mortbay.http.InclusiveByteRange;
import org.mortbay.http.MultiPartResponse;
import org.mortbay.http.ResourceCache;
import org.mortbay.util.CachedResource;
import org.mortbay.util.IO;
import org.mortbay.util.LogSupport;
import org.mortbay.util.Resource;
import org.mortbay.util.StringMap;
import org.mortbay.util.TypeUtil;
import org.mortbay.util.URI;
/* ------------------------------------------------------------ */
/** Handler to serve files and resources.
* Serves files from a given resource URL base and implements
* the GET, HEAD, DELETE, OPTIONS, PUT, MOVE methods and the
* IfModifiedSince and IfUnmodifiedSince header fields.
* A simple memory cache is also provided to reduce file I/O.
* HTTP/1.1 ranges are supported.
*
* @version $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $
* @author Nuno Pregui<75>a
* @author Greg Wilkins
*/
public class ResourceHandler extends AbstractHttpHandler
{
private static Log log = LogFactory.getLog(ResourceHandler.class);
/* ----------------------------------------------------------------- */
private boolean _acceptRanges=true;
private boolean _redirectWelcomeFiles ;
private String[] _methods=null;
private String _allowed;
private boolean _dirAllowed=true;
private int _minGzipLength =-1;
private StringMap _methodMap = new StringMap();
{
setAllowedMethods(new String[]
{
HttpRequest.__GET,
HttpRequest.__POST,
HttpRequest.__HEAD,
HttpRequest.__OPTIONS,
HttpRequest.__TRACE
});
}
/* ----------------------------------------------------------------- */
/** Construct a ResourceHandler.
*/
public ResourceHandler()
{}
/* ----------------------------------------------------------------- */
public synchronized void start()
throws Exception
{
super.start();
}
/* ----------------------------------------------------------------- */
public void stop()
throws InterruptedException
{
super.stop();
}
/* ------------------------------------------------------------ */
public String[] getAllowedMethods()
{
return _methods;
}
/* ------------------------------------------------------------ */
public void setAllowedMethods(String[] methods)
{
StringBuffer b = new StringBuffer();
_methods=methods;
_methodMap.clear();
for (int i=0;i<methods.length;i++)
{
_methodMap.put(methods[i],methods[i]);
if (i>0)
b.append(',');
b.append(methods[i]);
}
_allowed=b.toString();
}
/* ------------------------------------------------------------ */
public boolean isMethodAllowed(String method)
{
return _methodMap.get(method)!=null;
}
/* ------------------------------------------------------------ */
public String getAllowedString()
{
return _allowed;
}
/* ------------------------------------------------------------ */
public boolean isDirAllowed()
{
return _dirAllowed;
}
/* ------------------------------------------------------------ */
public void setDirAllowed(boolean dirAllowed)
{
_dirAllowed = dirAllowed;
}
/* ------------------------------------------------------------ */
public boolean isAcceptRanges()
{
return _acceptRanges;
}
/* ------------------------------------------------------------ */
/**
* @return True if welcome files are redirected to. False if forward is used.
*/
public boolean getRedirectWelcome()
{
return _redirectWelcomeFiles;
}
/* ------------------------------------------------------------ */
/**
* @param redirectWelcome True if welcome files are redirected to. False
* if forward is used.
*/
public void setRedirectWelcome(boolean redirectWelcome)
{
_redirectWelcomeFiles = redirectWelcome;
}
/* ------------------------------------------------------------ */
/** Set if the handler accepts range requests.
* Default is false;
* @param ar True if the handler should accept ranges
*/
public void setAcceptRanges(boolean ar)
{
_acceptRanges=ar;
}
/* ------------------------------------------------------------ */
/** Get minimum content length for GZIP encoding.
* @return Minimum length of content for gzip encoding or -1 if disabled.
*/
public int getMinGzipLength()
{
return _minGzipLength;
}
/* ------------------------------------------------------------ */
/** Set minimum content length for GZIP encoding.
* @param minGzipLength If set to a positive integer, then static content
* larger than this will be served as gzip content encoded
* if a matching resource is found ending with ".gz"
*/
public void setMinGzipLength(int minGzipLength)
{
_minGzipLength = minGzipLength;
}
/* ------------------------------------------------------------ */
/** get Resource to serve.
* Map a path to a resource. The default implementation calls
* HttpContext.getResource but derived handers may provide
* their own mapping.
* @param pathInContext The path to find a resource for.
* @return The resource to serve.
*/
protected Resource getResource(String pathInContext)
throws IOException
{
return getHttpContext().getResource(pathInContext);
}
/* ------------------------------------------------------------ */
public void handle(String pathInContext,
String pathParams,
HttpRequest request,
HttpResponse response)
throws HttpException, IOException
{
Resource resource = getResource(pathInContext);
if (resource==null)
return;
// Is the method allowed?
if (!isMethodAllowed(request.getMethod()))
{
if(log.isDebugEnabled())log.debug("Method not allowed: "+request.getMethod());
if (resource.exists())
{
setAllowHeader(response);
response.sendError(HttpResponse.__405_Method_Not_Allowed);
}
return;
}
// Handle the request
try
{
if(log.isDebugEnabled())log.debug("PATH="+pathInContext+" RESOURCE="+resource);
// check filename
String method=request.getMethod();
if (method.equals(HttpRequest.__GET) ||
method.equals(HttpRequest.__POST) ||
method.equals(HttpRequest.__HEAD))
handleGet(request, response, pathInContext, pathParams, resource);
else if (method.equals(HttpRequest.__PUT))
handlePut(request, response, pathInContext, resource);
else if (method.equals(HttpRequest.__DELETE))
handleDelete(request, response, pathInContext, resource);
else if (method.equals(HttpRequest.__OPTIONS))
handleOptions(response, pathInContext);
else if (method.equals(HttpRequest.__MOVE))
handleMove(request, response, pathInContext, resource);
else if (method.equals(HttpRequest.__TRACE))
handleTrace(request, response);
else
{
if(log.isDebugEnabled())log.debug("Unknown action:"+method);
// anything else...
try{
if (resource.exists())
response.sendError(HttpResponse.__501_Not_Implemented);
}
catch(Exception e) {LogSupport.ignore(log,e);}
}
}
catch(IllegalArgumentException e)
{
LogSupport.ignore(log,e);
}
finally
{
if (resource!=null && !(resource instanceof CachedResource))
resource.release();
}
}
/* ------------------------------------------------------------------- */
public void handleGet(HttpRequest request,
HttpResponse response,
String pathInContext,
String pathParams,
Resource resource)
throws IOException
{
if(log.isDebugEnabled())log.debug("Looking for "+resource);
if (resource!=null && resource.exists())
{
// check if directory
if (resource.isDirectory())
{
if (!pathInContext.endsWith("/") && !pathInContext.equals("/"))
{
log.debug("Redirect to directory/");
String q=request.getQuery();
// Properly fix URI
URI urifix = new URI(request.getRequestURL().toString());
urifix.setPath(urifix.getPath());
StringBuffer buf = new StringBuffer(urifix.toString());
urifix = null;
if (q!=null&&q.length()!=0)
{
buf.append('?');
buf.append(q);
}
response.setField(HttpFields.__Location, URI.addPaths(buf.toString(),"/"));
response.setStatus(302);
request.setHandled(true);
return;
}
// See if index file exists
String welcome=getHttpContext().getWelcomeFile(resource);
if (welcome!=null)
{
// Forward to the index
String ipath=URI.addPaths(pathInContext,welcome);
if (_redirectWelcomeFiles)
{
// Redirect to the index
ipath=URI.addPaths(getHttpContext().getContextPath(),ipath);
response.setContentLength(0);
response.sendRedirect(ipath);
}
else
{
URI uri=request.getURI();
uri.setPath(URI.addPaths(uri.getPath(),welcome));
getHttpContext().handle(ipath,pathParams,request,response);
}
return;
}
// Check modified dates
if (!passConditionalHeaders(request,response,resource))
return;
// If we got here, no forward to index took place
sendDirectory(request,response,resource,pathInContext.length()>1);
}
// check if it is a file
else if (resource.exists())
{
// Check modified dates
if (!passConditionalHeaders(request,response,resource))
return;
sendData(request,response,pathInContext,resource,true);
}
else
// don't know what it is
log.warn("Unknown file type");
}
}
/* ------------------------------------------------------------ */
/* Check modification date headers.
*/
private boolean passConditionalHeaders(HttpRequest request,
HttpResponse response,
Resource resource)
throws IOException
{
if (!request.getMethod().equals(HttpRequest.__HEAD))
{
// If we have meta data for the file
// Try a direct match for most common requests. Avoids
// parsing the date.
ResourceCache.ResourceMetaData metaData =
(ResourceCache.ResourceMetaData)resource.getAssociate();
if (metaData!=null)
{
String ifms=request.getField(HttpFields.__IfModifiedSince);
String mdlm=metaData.getLastModified();
if (ifms!=null && mdlm!=null && ifms.equals(mdlm))
{
response.setStatus(HttpResponse.__304_Not_Modified);
request.setHandled(true);
return false;
}
}
long date=0;
// Parse the if[un]modified dates and compare to resource
if ((date=request.getDateField(HttpFields.__IfUnmodifiedSince))>0)
{
if (resource.lastModified()/1000 > date/1000)
{
response.sendError(HttpResponse.__412_Precondition_Failed);
return false;
}
}
if ((date=request.getDateField(HttpFields.__IfModifiedSince))>0)
{
if (resource.lastModified()/1000 <= date/1000)
{
response.setStatus(HttpResponse.__304_Not_Modified);
request.setHandled(true);
return false;
}
}
}
return true;
}
/* ------------------------------------------------------------ */
void handlePut(HttpRequest request,
HttpResponse response,
String pathInContext,
Resource resource)
throws IOException
{
if(log.isDebugEnabled())log.debug("PUT "+pathInContext+" in "+resource);
boolean exists=resource!=null && resource.exists();
if (exists &&
!passConditionalHeaders(request,response,resource))
return;
if (pathInContext.endsWith("/"))
{
if (!exists)
{
if (!resource.getFile().mkdirs())
response.sendError(HttpResponse.__403_Forbidden, "Directories could not be created");
else
{
request.setHandled(true);
response.setStatus(HttpResponse.__201_Created);
response.commit();
}
}
else
{
request.setHandled(true);
response.setStatus(HttpResponse.__200_OK);
response.commit();
}
}
else
{
try
{
int toRead = request.getContentLength();
InputStream in = request.getInputStream();
OutputStream out = resource.getOutputStream();
if (toRead>=0)
IO.copy(in,out,toRead);
else
IO.copy(in,out);
out.close();
request.setHandled(true);
response.setStatus(exists
?HttpResponse.__200_OK
:HttpResponse.__201_Created);
response.commit();
}
catch (Exception ex)
{
log.warn(LogSupport.EXCEPTION,ex);
response.sendError(HttpResponse.__403_Forbidden,
ex.getMessage());
}
}
}
/* ------------------------------------------------------------ */
void handleDelete(HttpRequest request,
HttpResponse response,
String pathInContext,
Resource resource)
throws IOException
{
if(log.isDebugEnabled())log.debug("DELETE "+pathInContext+" from "+resource);
if (!resource.exists() ||
!passConditionalHeaders(request,response,resource))
return;
try
{
// delete the file
if (resource.delete())
response.setStatus(HttpResponse.__204_No_Content);
else
response.sendError(HttpResponse.__403_Forbidden);
// Send response
request.setHandled(true);
}
catch (SecurityException sex)
{
log.warn(LogSupport.EXCEPTION,sex);
response.sendError(HttpResponse.__403_Forbidden, sex.getMessage());
}
}
/* ------------------------------------------------------------ */
void handleMove(HttpRequest request,
HttpResponse response,
String pathInContext,
Resource resource)
throws IOException
{
if (!resource.exists() || !passConditionalHeaders(request,response,resource))
return;
String newPath = URI.canonicalPath(request.getField("New-uri"));
if (newPath==null)
{
response.sendError(HttpResponse.__405_Method_Not_Allowed,
"Bad new uri");
return;
}
String contextPath = getHttpContext().getContextPath();
if (contextPath!=null && !newPath.startsWith(contextPath))
{
response.sendError(HttpResponse.__405_Method_Not_Allowed,
"Not in context");
return;
}
// Find path
try
{
// TODO - Check this
String newInfo=newPath;
if (contextPath!=null)
newInfo=newInfo.substring(contextPath.length());
Resource newFile = getHttpContext().getBaseResource().addPath(newInfo);
if(log.isDebugEnabled())log.debug("Moving "+resource+" to "+newFile);
resource.renameTo(newFile);
response.setStatus(HttpResponse.__204_No_Content);
request.setHandled(true);
}
catch (Exception ex)
{
log.warn(LogSupport.EXCEPTION,ex);
setAllowHeader(response);
response.sendError(HttpResponse.__405_Method_Not_Allowed,
"Error:"+ex);
return;
}
}
/* ------------------------------------------------------------ */
void handleOptions(HttpResponse response, String pathInContext)
throws IOException
{
if ("*".equals(pathInContext))
return;
setAllowHeader(response);
response.commit();
}
/* ------------------------------------------------------------ */
void setAllowHeader(HttpResponse response)
{
response.setField(HttpFields.__Allow, getAllowedString());
}
/* ------------------------------------------------------------ */
public void writeHeaders(HttpResponse response,Resource resource, long count)
throws IOException
{
ResourceCache.ResourceMetaData metaData =
(ResourceCache.ResourceMetaData)resource.getAssociate();
response.setContentType(metaData.getMimeType());
if (count != -1)
{
if (count==resource.length())
response.setField(HttpFields.__ContentLength,metaData.getLength());
else
response.setContentLength((int)count);
}
response.setField(HttpFields.__LastModified,metaData.getLastModified());
if (_acceptRanges && response.getHttpRequest().getDotVersion()>0)
response.setField(HttpFields.__AcceptRanges,"bytes");
}
/* ------------------------------------------------------------ */
public void sendData(HttpRequest request,
HttpResponse response,
String pathInContext,
Resource resource,
boolean writeHeaders)
throws IOException
{
long resLength=resource.length();
// see if there are any range headers
Enumeration reqRanges =
request.getDotVersion()>0
?request.getFieldValues(HttpFields.__Range)
:null;
if (!writeHeaders || reqRanges == null || !reqRanges.hasMoreElements())
{
// look for a gziped content.
Resource data=resource;
if (_minGzipLength>0)
{
String accept=request.getField(HttpFields.__AcceptEncoding);
if (accept!=null && resLength>_minGzipLength &&
!pathInContext.endsWith(".gz"))
{
Resource gz = getHttpContext().getResource(pathInContext+".gz");
if (gz.exists() && accept.indexOf("gzip")>=0)
{
if(log.isDebugEnabled())log.debug("gzip="+gz);
response.setField(HttpFields.__ContentEncoding,"gzip");
data=gz;
resLength=data.length();
}
}
}
writeHeaders(response,resource,resLength);
request.setHandled(true);
OutputStream out = response.getOutputStream();
data.writeTo(out,0,resLength);
return;
}
// Parse the satisfiable ranges
List ranges =InclusiveByteRange.satisfiableRanges(reqRanges,resLength);
if(log.isDebugEnabled())log.debug("ranges: " + reqRanges + " == " + ranges);
// if there are no satisfiable ranges, send 416 response
if (ranges==null || ranges.size()==0)
{
log.debug("no satisfiable ranges");
writeHeaders(response, resource, resLength);
response.setStatus(HttpResponse.__416_Requested_Range_Not_Satisfiable);
response.setReason((String)HttpResponse.__statusMsg
.get(TypeUtil.newInteger(HttpResponse.__416_Requested_Range_Not_Satisfiable)));
response.setField(HttpFields.__ContentRange,
InclusiveByteRange.to416HeaderRangeString(resLength));
OutputStream out = response.getOutputStream();
resource.writeTo(out,0,resLength);
request.setHandled(true);
return;
}
// if there is only a single valid range (must be satisfiable
// since were here now), send that range with a 216 response
if ( ranges.size()== 1)
{
InclusiveByteRange singleSatisfiableRange =
(InclusiveByteRange)ranges.get(0);
if(log.isDebugEnabled())log.debug("single satisfiable range: " + singleSatisfiableRange);
long singleLength = singleSatisfiableRange.getSize(resLength);
writeHeaders(response,resource,singleLength);
response.setStatus(HttpResponse.__206_Partial_Content);
response.setReason((String)HttpResponse.__statusMsg
.get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
response.setField(HttpFields.__ContentRange,
singleSatisfiableRange.toHeaderRangeString(resLength));
OutputStream out = response.getOutputStream();
resource.writeTo(out,
singleSatisfiableRange.getFirst(resLength),
singleLength);
request.setHandled(true);
return;
}
// multiple non-overlapping valid ranges cause a multipart
// 216 response which does not require an overall
// content-length header
//
ResourceCache.ResourceMetaData metaData =
(ResourceCache.ResourceMetaData)resource.getAssociate();
String encoding = metaData.getMimeType();
MultiPartResponse multi = new MultiPartResponse(response);
response.setStatus(HttpResponse.__206_Partial_Content);
response.setReason((String)HttpResponse.__statusMsg
.get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
// If the request has a "Request-Range" header then we need to
// send an old style multipart/x-byteranges Content-Type. This
// keeps Netscape and acrobat happy. This is what Apache does.
String ctp;
if (request.containsField(HttpFields.__RequestRange))
ctp = "multipart/x-byteranges; boundary=";
else
ctp = "multipart/byteranges; boundary=";
response.setContentType(ctp+multi.getBoundary());
InputStream in=(resource instanceof CachedResource)
?null:resource.getInputStream();
OutputStream out = response.getOutputStream();
long pos=0;
for (int i=0;i<ranges.size();i++)
{
InclusiveByteRange ibr = (InclusiveByteRange) ranges.get(i);
String header=HttpFields.__ContentRange+": "+
ibr.toHeaderRangeString(resLength);
if(log.isDebugEnabled())log.debug("multi range: "+encoding+" "+header);
multi.startPart(encoding,new String[]{header});
long start=ibr.getFirst(resLength);
long size=ibr.getSize(resLength);
if (in!=null)
{
// Handle non cached resource
if (start<pos)
{
in.close();
in=resource.getInputStream();
pos=0;
}
if (pos<start)
{
in.skip(start-pos);
pos=start;
}
IO.copy(in,out,size);
pos+=size;
}
else
// Handle cached resource
resource.writeTo(out,start,size);
}
if (in!=null)
in.close();
multi.close();
request.setHandled(true);
return;
}
/* ------------------------------------------------------------------- */
void sendDirectory(HttpRequest request,
HttpResponse response,
Resource resource,
boolean parent)
throws IOException
{
if (!_dirAllowed)
{
response.sendError(HttpResponse.__403_Forbidden);
return;
}
request.setHandled(true);
if(log.isDebugEnabled())log.debug("sendDirectory: "+resource);
byte[] data=null;
if (resource instanceof CachedResource)
data=((CachedResource)resource).getCachedData();
if (data==null)
{
String base = URI.addPaths(request.getPath(),"/");
String dir = resource.getListHTML(URI.encodePath(base),parent);
if (dir==null)
{
response.sendError(HttpResponse.__403_Forbidden,
"No directory");
return;
}
data=dir.getBytes("UTF8");
if (resource instanceof CachedResource)
((CachedResource)resource).setCachedData(data);
}
response.setContentType("text/html; charset=UTF8");
response.setContentLength(data.length);
if (request.getMethod().equals(HttpRequest.__HEAD))
{
response.commit();
return;
}
response.getOutputStream().write(data,0,data.length);
response.commit();
}
}

View File

@@ -0,0 +1,352 @@
// ========================================================================
// $Id: FileResource.java,v 1.31 2006/01/04 13:55:31 gregwilkins Exp $
// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
package org.mortbay.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.security.Permission;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
/* ------------------------------------------------------------ */
/** File Resource.
*
* Handle resources of implied or explicit file type.
* This class can check for aliasing in the filesystem (eg case
* insensitivity). By default this is turned on if the platform does
* not have the "/" path separator, or it can be controlled with the
* "org.mortbay.util.FileResource.checkAliases" system parameter.
*
* If alias checking is turned on, then aliased resources are
* treated as if they do not exist, nor can they be created.
*
* @version $Revision: 1.31 $
* @author Greg Wilkins (gregw)
*/
public class FileResource extends URLResource
{
private static Log log = LogFactory.getLog(Credential.class);
private static boolean __checkAliases;
static
{
__checkAliases=
"true".equalsIgnoreCase
(System.getProperty("org.mortbay.util.FileResource.checkAliases","true"));
if (__checkAliases)
log.info("Checking Resource aliases");
}
/* ------------------------------------------------------------ */
private File _file;
private transient URL _alias=null;
private transient boolean _aliasChecked=false;
/* ------------------------------------------------------------------------------- */
/** setCheckAliases.
* @param checkAliases True of resource aliases are to be checked for (eg case insensitivity or 8.3 short names) and treated as not found.
*/
public static void setCheckAliases(boolean checkAliases)
{
__checkAliases=checkAliases;
}
/* ------------------------------------------------------------------------------- */
/** getCheckAliases.
* @return True of resource aliases are to be checked for (eg case insensitivity or 8.3 short names) and treated as not found.
*/
public static boolean getCheckAliases()
{
return __checkAliases;
}
/* -------------------------------------------------------- */
FileResource(URL url)
throws IOException, URISyntaxException
{
super(url,null);
try
{
// Try standard API to convert URL to file.
_file =new File(new URI(url.toString()));
}
catch (Exception e)
{
LogSupport.ignore(log,e);
try
{
// Assume that File.toURL produced unencoded chars. So try
// encoding them.
String urls=
"file:"+org.mortbay.util.URI.encodePath(url.toString().substring(5));
_file =new File(new URI(urls));
}
catch (Exception e2)
{
LogSupport.ignore(log,e2);
// Still can't get the file. Doh! try good old hack!
checkConnection();
Permission perm = _connection.getPermission();
_file = new File(perm==null?url.getFile():perm.getName());
}
}
if (_file.isDirectory() && !_urlString.endsWith("/"))
_urlString=_urlString+"/";
}
/* -------------------------------------------------------- */
FileResource(URL url, URLConnection connection, File file)
{
super(url,connection);
_file=file;
if (_file.isDirectory() && !_urlString.endsWith("/"))
_urlString=_urlString+"/";
}
/* -------------------------------------------------------- */
public Resource addPath(String path)
throws IOException,MalformedURLException
{
FileResource r=null;
if (!isDirectory())
{
r=(FileResource)super.addPath(path);
}
else
{
path = org.mortbay.util.URI.canonicalPath(path);
// treat all paths being added as relative
String rel=path;
if (path.startsWith("/"))
rel = path.substring(1);
File newFile = new File(_file,rel.replace('/', File.separatorChar));
r=new FileResource(newFile.toURI().toURL(),null,newFile);
}
String encoded=org.mortbay.util.URI.encodePath(path);
int expected=r._urlString.length()-encoded.length();
int index = r._urlString.lastIndexOf(encoded, expected);
if (expected!=index && ((expected-1)!=index || path.endsWith("/") || !r.isDirectory()))
{
r._alias=r._url;
r._aliasChecked=true;
}
return r;
}
/* ------------------------------------------------------------ */
public URL getAlias()
{
if (__checkAliases) {
if (!_aliasChecked)
{
try
{
String abs=_file.getAbsolutePath();
String can=_file.getCanonicalPath();
if (abs.length()!=can.length() || !abs.equals(can))
_alias=new File(can).toURI().toURL();
_aliasChecked=true;
if (_alias!=null && log.isDebugEnabled())
{
log.debug("ALIAS abs="+abs);
log.debug("ALIAS can="+can);
}
}
catch(Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
return getURL();
}
}
} else return null;
return _alias;
}
/* -------------------------------------------------------- */
/**
* Returns true if the resource exists.
*/
public boolean exists()
{
return _file.exists();
}
/* -------------------------------------------------------- */
/**
* Returns the last modified time
*/
public long lastModified()
{
return _file.lastModified();
}
/* -------------------------------------------------------- */
/**
* Returns true if the respresenetd resource is a container/directory.
*/
public boolean isDirectory()
{
return _file.isDirectory();
}
/* --------------------------------------------------------- */
/**
* Return the length of the resource
*/
public long length()
{
return _file.length();
}
/* --------------------------------------------------------- */
/**
* Returns the name of the resource
*/
public String getName()
{
return _file.getAbsolutePath();
}
/* ------------------------------------------------------------ */
/**
* Returns an File representing the given resource or NULL if this
* is not possible.
*/
public File getFile()
{
return _file;
}
/* --------------------------------------------------------- */
/**
* Returns an input stream to the resource
*/
public InputStream getInputStream() throws IOException
{
return new FileInputStream(_file);
}
/* --------------------------------------------------------- */
/**
* Returns an output stream to the resource
*/
public OutputStream getOutputStream()
throws java.io.IOException, SecurityException
{
return new FileOutputStream(_file);
}
/* --------------------------------------------------------- */
/**
* Deletes the given resource
*/
public boolean delete()
throws SecurityException
{
return _file.delete();
}
/* --------------------------------------------------------- */
/**
* Rename the given resource
*/
public boolean renameTo( Resource dest)
throws SecurityException
{
if( dest instanceof FileResource)
return _file.renameTo( ((FileResource)dest)._file);
else
return false;
}
/* --------------------------------------------------------- */
/**
* Returns a list of resources contained in the given resource
*/
public String[] list()
{
String[] list =_file.list();
if (list==null)
return null;
for (int i=list.length;i-->0;)
{
if (new File(_file,list[i]).isDirectory() &&
!list[i].endsWith("/"))
list[i]+="/";
}
return list;
}
/* ------------------------------------------------------------ */
/** Encode according to this resource type.
* File URIs are encoded.
* @param uri URI to encode.
* @return The uri unchanged.
*/
public String encode(String uri)
{
return uri;
}
/* ------------------------------------------------------------ */
/**
* @param o
* @return
*/
public boolean equals( Object o)
{
if (this == o)
return true;
if (null == o || ! (o instanceof FileResource))
return false;
FileResource f=(FileResource)o;
return f._file == _file || (null != _file && _file.equals(f._file));
}
/* ------------------------------------------------------------ */
/**
* @return the hashcode.
*/
public int hashCode()
{
return null == _file ? super.hashCode() : _file.hashCode();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,9 +19,10 @@ public interface I2PServerSocket {
/**
* Waits for the next socket connecting. If a remote user tried to make a
* connection and the local application wasn't .accept()ing new connections,
* they should get refused (if .accept() doesnt occur in some small period)
* they should get refused (if .accept() doesnt occur in some small period).
* Warning - unlike regular ServerSocket, may return null.
*
* @return a connected I2PSocket
* @return a connected I2PSocket OR NULL
*
* @throws I2PException if there is a problem with reading a new socket
* from the data available (aka the I2PSession closed, etc)

View File

@@ -9,6 +9,7 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import net.i2p.router.client.ClientManagerFacadeImpl;
import net.i2p.router.startup.ClientAppConfig;
import net.i2p.router.startup.LoadClientAppsJob;
@@ -35,6 +36,10 @@ public class ConfigClientsHandler extends FormHandler {
saveClientChanges();
return;
}
if (_action.equals(_("Save Interface Configuration"))) {
saveInterfaceChanges();
return;
}
if (_action.equals(_("Save WebApp Configuration"))) {
saveWebAppChanges();
return;
@@ -193,7 +198,7 @@ public class ConfigClientsHandler extends FormHandler {
String[] arr = (String[]) _settings.get(key);
if (arr == null)
return null;
return arr[0];
return arr[0].trim();
}
private void startClient(int i) {
@@ -337,4 +342,37 @@ public class ConfigClientsHandler extends FormHandler {
_log.error("Error starting plugin " + app, e);
}
}
/**
* Handle interface form
* @since 0.8.3
*/
private void saveInterfaceChanges() {
String port = getJettyString("port");
if (port != null)
_context.router().setConfigSetting(ClientManagerFacadeImpl.PROP_CLIENT_PORT, port);
String intfc = getJettyString("interface");
if (intfc != null)
_context.router().setConfigSetting(ClientManagerFacadeImpl.PROP_CLIENT_HOST, intfc);
String user = getJettyString("user");
if (user != null)
_context.router().setConfigSetting(ConfigClientsHelper.PROP_USER, user);
String pw = getJettyString("pw");
if (pw != null)
_context.router().setConfigSetting(ConfigClientsHelper.PROP_PW, pw);
String mode = getJettyString("mode");
boolean disabled = "0".equals(mode);
boolean ssl = "2".equals(mode);
_context.router().setConfigSetting(ConfigClientsHelper.PROP_DISABLE_EXTERNAL,
Boolean.toString(disabled));
_context.router().setConfigSetting(ConfigClientsHelper.PROP_ENABLE_SSL,
Boolean.toString(ssl));
_context.router().setConfigSetting(ConfigClientsHelper.PROP_AUTH,
Boolean.toString((_settings.get("auth") != null)));
boolean all = "0.0.0.0".equals(intfc) || "0:0:0:0:0:0:0:0".equals(intfc) ||
"::".equals(intfc);
_context.router().setConfigSetting(ConfigClientsHelper.BIND_ALL_INTERFACES, Boolean.toString(all));
_context.router().saveConfig();
addFormNotice(_("Interface configuration saved successfully - restart required to take effect."));
}
}

View File

@@ -1,6 +1,7 @@
package net.i2p.router.web;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -8,13 +9,76 @@ import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import net.i2p.router.client.ClientManagerFacadeImpl;
import net.i2p.router.startup.ClientAppConfig;
import net.i2p.util.Addresses;
public class ConfigClientsHelper extends HelperBase {
private String _edit;
/** from ClientListenerRunner */
public static final String BIND_ALL_INTERFACES = "i2cp.tcp.bindAllInterfaces";
/** from ClientManager */
public static final String PROP_DISABLE_EXTERNAL = "i2cp.disableInterface";
public static final String PROP_ENABLE_SSL = "i2cp.SSL";
/** from ClientMessageEventListener */
public static final String PROP_AUTH = "i2cp.auth";
public static final String PROP_USER = "i2cp.username";
public static final String PROP_PW = "i2cp.password";
public ConfigClientsHelper() {}
/** @since 0.8.3 */
public String getPort() {
return _context.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_PORT,
Integer.toString(ClientManagerFacadeImpl.DEFAULT_PORT));
}
/** @since 0.8.3 */
public String getUser() {
return _context.getProperty(PROP_USER, "");
}
/** @since 0.8.3 */
public String getPw() {
return _context.getProperty(PROP_PW, "");
}
/** @since 0.8.3 */
public String i2cpModeChecked(int mode) {
boolean disabled = _context.getBooleanProperty(PROP_DISABLE_EXTERNAL);
boolean ssl = _context.getBooleanProperty(PROP_ENABLE_SSL);
if ((mode == 0 && disabled) ||
(mode == 1 && (!disabled) && (!ssl)) ||
(mode == 2 && (!disabled) && ssl))
return "checked=\"true\"";
return "";
}
/** @since 0.8.3 */
public String getAuth() {
boolean enabled = _context.getBooleanProperty(PROP_AUTH);
if (enabled)
return "checked=\"true\"";
return "";
}
/** @since 0.8.3 */
public String[] intfcAddresses() {
ArrayList<String> al = new ArrayList(Addresses.getAllAddresses());
return al.toArray(new String[al.size()]);
}
/** @since 0.8.3 */
public boolean isIFSelected(String addr) {
boolean bindAll = _context.getBooleanProperty(BIND_ALL_INTERFACES);
if (bindAll && addr.equals("0.0.0.0") || addr.equals("::"))
return true;
String host = _context.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_HOST,
ClientManagerFacadeImpl.DEFAULT_HOST);
return (host.equals(addr));
}
public void setEdit(String edit) {
if (edit == null)
return;
@@ -41,7 +105,9 @@ public class ConfigClientsHelper extends HelperBase {
for (int cur = 0; cur < clients.size(); cur++) {
ClientAppConfig ca = clients.get(cur);
renderForm(buf, ""+cur, ca.clientName, false, !ca.disabled,
"webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName),
// dangerous, but allow editing the console args too
//"webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName),
false,
ca.className + ((ca.args != null) ? " " + ca.args : ""), (""+cur).equals(_edit),
true, false, false, true, ca.disabled);
}
@@ -92,9 +158,9 @@ public class ConfigClientsHelper extends HelperBase {
continue;
StringBuilder desc = new StringBuilder(256);
desc.append("<table border=\"0\">")
.append("<tr><td><b>").append(_("Version")).append("<td>").append(stripHTML(appProps, "version"))
.append("<tr><td><b>").append(_("Version")).append("</b></td><td>").append(stripHTML(appProps, "version"))
.append("<tr><td><b>")
.append(_("Signed by")).append("<td>");
.append(_("Signed by")).append("</b></td><td>");
String s = stripHTML(appProps, "signer");
if (s != null) {
if (s.indexOf("@") > 0)
@@ -111,13 +177,13 @@ public class ConfigClientsHelper extends HelperBase {
if (ms > 0) {
String date = (new SimpleDateFormat("yyyy-MM-dd HH:mm")).format(new Date(ms));
desc.append("<tr><td><b>")
.append(_("Date")).append("<td>").append(date);
.append(_("Date")).append("</b></td><td>").append(date);
}
}
s = stripHTML(appProps, "author");
if (s != null) {
desc.append("<tr><td><b>")
.append(_("Author")).append("<td>");
.append(_("Author")).append("</b></td><td>");
if (s.indexOf("@") > 0)
desc.append("<a href=\"mailto:").append(s).append("\">").append(s).append("</a>");
else
@@ -128,12 +194,12 @@ public class ConfigClientsHelper extends HelperBase {
s = stripHTML(appProps, "description");
if (s != null) {
desc.append("<tr><td><b>")
.append(_("Description")).append("<td>").append(s);
.append(_("Description")).append("</b></td><td>").append(s);
}
s = stripHTML(appProps, "license");
if (s != null) {
desc.append("<tr><td><b>")
.append(_("License")).append("<td>").append(s);
.append(_("License")).append("</b></td><td>").append(s);
}
s = stripHTML(appProps, "websiteURL");
if (s != null) {

View File

@@ -38,7 +38,7 @@ public class ConfigLoggingHelper extends HelperBase {
sortedLogs.add(prefix);
}
buf.append("<textarea name=\"levels\" rows=\"4\" cols=\"60\" wrap=\"off\">");
buf.append("<textarea name=\"levels\" rows=\"4\" cols=\"60\" wrap=\"off\" spellcheck=\"false\">");
for (Iterator iter = sortedLogs.iterator(); iter.hasNext(); ) {
String prefix = (String)iter.next();
String level = limits.getProperty(prefix);

View File

@@ -12,12 +12,12 @@ public class ConfigNavHelper extends HelperBase {
private static final String pages[] =
{"", "ui", "service", "update", "tunnels",
"clients", "peer", "keyring", "logging", "stats",
"advanced" };
"reseed", "advanced" };
private static final String titles[] =
{_x("Network"), _x("UI"), _x("Service"), _x("Update"), _x("Tunnels"),
_x("Clients"), _x("Peers"), _x("Keyring"), _x("Logging"), _x("Stats"),
_x("Advanced") };
_x("Reseeding"), _x("Advanced") };
public void renderNavBar(String requestURI) throws IOException {
StringBuilder buf = new StringBuilder(1024);

View File

@@ -1,14 +1,16 @@
package net.i2p.router.web;
import java.util.ArrayList;
import net.i2p.data.DataHelper;
import net.i2p.data.RouterAddress;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.Router;
import net.i2p.router.transport.Addresses;
import net.i2p.router.transport.TransportManager;
import net.i2p.router.transport.udp.UDPAddress;
import net.i2p.router.transport.udp.UDPTransport;
import net.i2p.time.Timestamper;
import net.i2p.util.Addresses;
public class ConfigNetHelper extends HelperBase {
public ConfigNetHelper() {}
@@ -147,7 +149,8 @@ public class ConfigNetHelper extends HelperBase {
}
public String[] getAddresses() {
return Addresses.getAddresses();
ArrayList<String> al = new ArrayList(Addresses.getAddresses());
return al.toArray(new String[al.size()]);
}
public String getInboundRate() {

View File

@@ -0,0 +1,68 @@
package net.i2p.router.web;
import java.util.HashMap;
import java.util.Map;
import net.i2p.router.networkdb.reseed.Reseeder;
/**
* @since 0.8.3
*/
public class ConfigReseedHandler extends FormHandler {
private Map _settings;
@Override
protected void processForm() {
if (_action.equals(_("Save changes and reseed now"))) {
saveChanges();
boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue();
if (reseedInProgress) {
addFormError(_("Reseeding is already in progress"));
} else {
// skip the nonce checking in ReseedHandler
addFormNotice(_("Starting reseed process"));
(new ReseedHandler(_context)).requestReseed();
}
return;
}
if (_action.equals(_("Save changes"))) {
saveChanges();
return;
}
addFormError(_("Unsupported") + ' ' + _action + '.');
}
public void setSettings(Map settings) { _settings = new HashMap(settings); }
/** curses Jetty for returning arrays */
private String getJettyString(String key) {
String[] arr = (String[]) _settings.get(key);
if (arr == null)
return null;
return arr[0].trim();
}
private void saveChanges() {
String port = getJettyString("port");
if (port != null)
_context.router().setConfigSetting(Reseeder.PROP_PROXY_PORT, port);
String host = getJettyString("host");
if (host != null)
_context.router().setConfigSetting(Reseeder.PROP_PROXY_HOST, host);
String url = getJettyString("reseedURL");
if (url != null)
_context.router().setConfigSetting(Reseeder.PROP_RESEED_URL, url.trim().replace("\r\n", ",").replace("\n", ","));
String mode = getJettyString("mode");
boolean req = "1".equals(mode);
boolean disabled = "2".equals(mode);
_context.router().setConfigSetting(Reseeder.PROP_SSL_REQUIRED,
Boolean.toString(req));
_context.router().setConfigSetting(Reseeder.PROP_SSL_DISABLE,
Boolean.toString(disabled));
boolean proxy = getJettyString("enable") != null;
_context.router().setConfigSetting(Reseeder.PROP_PROXY_ENABLE, Boolean.toString(proxy));
_context.router().saveConfig();
addFormNotice(_("Configuration saved successfully."));
}
}

View File

@@ -0,0 +1,58 @@
package net.i2p.router.web;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import net.i2p.router.networkdb.reseed.Reseeder;
/**
* @since 0.8.3
*/
public class ConfigReseedHelper extends HelperBase {
public String getPort() {
return _context.getProperty(Reseeder.PROP_PROXY_PORT, "");
}
public String getHost() {
return _context.getProperty(Reseeder.PROP_PROXY_HOST, "");
}
public String modeChecked(int mode) {
boolean required = _context.getBooleanProperty(Reseeder.PROP_SSL_REQUIRED);
boolean disabled = _context.getBooleanProperty(Reseeder.PROP_SSL_DISABLE);
if ((mode == 0 && (!disabled) && (!required)) ||
(mode == 1 && (!disabled) && required) ||
(mode == 2 && disabled))
return "checked=\"true\"";
return "";
}
public String getEnable() {
boolean enabled = _context.getBooleanProperty(Reseeder.PROP_PROXY_ENABLE);
if (enabled)
return "checked=\"true\"";
return "";
}
public String getReseedURL() {
String urls = _context.getProperty(Reseeder.PROP_RESEED_URL, Reseeder.DEFAULT_SEED_URL + ',' + Reseeder.DEFAULT_SSL_SEED_URL);
StringTokenizer tok = new StringTokenizer(urls, " ,\r\n");
List<String> URLList = new ArrayList(16);
while (tok.hasMoreTokens()) {
String s = tok.nextToken().trim();
if (s.length() > 0)
URLList.add(s);
}
Collections.sort(URLList);
StringBuilder buf = new StringBuilder();
for (String s : URLList) {
if (buf.length() > 0)
buf.append('\n');
buf.append(s);
}
return buf.toString();
}
}

View File

@@ -139,6 +139,6 @@ public class ConfigStatsHelper extends HelperBase {
public boolean getCurrentCanBeGraphed() { return _currentCanBeGraphed; }
public String getExplicitFilter() { return _filter; }
public boolean getIsFull() {
return _context.getBooleanPropertyDefaultTrue(StatManager.PROP_STAT_FULL);
return _context.getBooleanProperty(StatManager.PROP_STAT_FULL);
}
}

View File

@@ -3,6 +3,7 @@ package net.i2p.router.web;
import net.i2p.I2PAppContext;
import net.i2p.crypto.TrustedUpdate;
import net.i2p.data.DataHelper;
import net.i2p.util.FileUtil;
/**
*
@@ -61,14 +62,10 @@ public class ConfigUpdateHandler extends FormHandler {
public static final String DEFAULT_UPDATE_URL;
static {
String foo;
try {
Class.forName("java.util.jar.Pack200", false, ClassLoader.getSystemClassLoader());
foo = PACK200_URLS;
} catch (ClassNotFoundException cnfe) {
foo = NO_PACK200_URLS;
}
DEFAULT_UPDATE_URL = foo;
if (FileUtil.isPack200Supported())
DEFAULT_UPDATE_URL = PACK200_URLS;
else
DEFAULT_UPDATE_URL = NO_PACK200_URLS;
}
public static final String PROP_TRUSTED_KEYS = "router.trustedUpdateKeys";

View File

@@ -59,7 +59,13 @@ public class GraphHelper extends FormHandler {
try { _width = Math.min(Integer.parseInt(str), MAX_X); } catch (NumberFormatException nfe) {}
}
public void setRefreshDelay(String str) {
try { _refreshDelaySeconds = Math.max(Integer.parseInt(str), MIN_REFRESH); } catch (NumberFormatException nfe) {}
try {
int rds = Integer.parseInt(str);
if (rds > 0)
_refreshDelaySeconds = Math.max(rds, MIN_REFRESH);
else
_refreshDelaySeconds = -1;
} catch (NumberFormatException nfe) {}
}
public String getImages() {
@@ -83,7 +89,7 @@ public class GraphHelper extends FormHandler {
+ "&amp;periodCount=" + (3 * _periodCount )
+ "&amp;width=" + (3 * _width)
+ "&amp;height=" + (3 * _height)
+ "\" / target=\"_blank\">");
+ "\" target=\"_blank\">");
String title = _("Combined bandwidth graph");
_out.write("<img class=\"statimage\" width=\""
+ (_width + 83) + "\" height=\"" + (_height + 92)
@@ -129,6 +135,8 @@ public class GraphHelper extends FormHandler {
return "";
}
private static final int[] times = { 60, 2*60, 5*60, 10*60, 30*60, 60*60, -1 };
public String getForm() {
String prev = System.getProperty("net.i2p.router.web.GraphHelper.nonce");
if (prev != null) System.setProperty("net.i2p.router.web.GraphHelper.noncePrev", prev);
@@ -145,8 +153,22 @@ public class GraphHelper extends FormHandler {
_out.write(_("Image sizes") + ": " + _("width") + ": <input size=\"4\" type=\"text\" name=\"width\" value=\"" + _width
+ "\"> " + _("pixels") + ", " + _("height") + ": <input size=\"4\" type=\"text\" name=\"height\" value=\"" + _height
+ "\"> " + _("pixels") + "<br>\n");
_out.write(_("Refresh delay") + ": <select name=\"refreshDelay\"><option value=\"60\">1 " + _("minute") + "</option><option value=\"120\">2 " + _("minutes") + "</option><option value=\"300\">5 " + _("minutes") + "</option><option value=\"600\">10 " + _("minutes") + "</option><option value=\"1800\">30 " + _("minutes") + "</option><option value=\"3600\">1 " + _("hour") + "</option><option value=\"-1\">" + _("Never") + "</option></select><br>\n");
_out.write("<hr><div class=\"formaction\"><input type=\"submit\" value=\"" + _("Redraw") + "\"></div></form>");
_out.write(_("Refresh delay") + ": <select name=\"refreshDelay\">");
for (int i = 0; i < times.length; i++) {
_out.write("<option value=\"");
_out.write(Integer.toString(times[i]));
_out.write("\"");
if (times[i] == _refreshDelaySeconds)
_out.write(" selected=\"true\"");
_out.write(">");
if (times[i] > 0)
_out.write(DataHelper.formatDuration2(times[i] * 1000));
else
_out.write(_("Never"));
_out.write("</option>\n");
}
_out.write("</select><br>\n" +
"<hr><div class=\"formaction\"><input type=\"submit\" value=\"" + _("Redraw") + "\"></div></form>");
} catch (IOException ioe) {
ioe.printStackTrace();
}

View File

@@ -53,7 +53,8 @@ public class LocaleWebAppHandler extends WebApplicationHandler
// home page
pathInContext = "/index.jsp";
} else if (pathInContext.indexOf("/", 1) < 0 &&
!pathInContext.endsWith(".jsp")) {
(!pathInContext.endsWith(".jsp")) &&
(!pathInContext.endsWith(".txt"))) {
// add .jsp to pages at top level
pathInContext += ".jsp";
}

View File

@@ -144,6 +144,7 @@ public class PluginUpdateHandler extends UpdateHandler {
}
buf.append(": ");
buf.append(_("{0}B transferred", DataHelper.formatSize2(currentWrite + alreadyTransferred)));
buf.append("</b>");
updateStatus(buf.toString());
}

View File

@@ -4,37 +4,54 @@ import java.util.ArrayList;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.security.KeyStore;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.apps.systray.SysTray;
import net.i2p.data.Base32;
import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.ShellCommand;
import org.mortbay.http.DigestAuthenticator;
import org.mortbay.http.HashUserRealm;
import org.mortbay.http.NCSARequestLog;
import org.mortbay.http.SecurityConstraint;
import org.mortbay.http.SslListener;
import org.mortbay.http.handler.SecurityHandler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.WebApplicationContext;
import org.mortbay.jetty.servlet.WebApplicationHandler;
import org.mortbay.util.InetAddrPort;
public class RouterConsoleRunner {
private Server _server;
private String _listenPort = "7657";
private String _listenHost = "127.0.0.1";
private String _webAppsDir = "./webapps/";
private String _listenPort;
private String _listenHost;
private String _sslListenPort;
private String _sslListenHost;
private String _webAppsDir;
private static final String PROP_WEBAPP_CONFIG_FILENAME = "router.webappsConfigFile";
private static final String DEFAULT_WEBAPP_CONFIG_FILENAME = "webapps.config";
private static final DigestAuthenticator authenticator = new DigestAuthenticator();
public static final String ROUTERCONSOLE = "routerconsole";
public static final String PREFIX = "webapps.";
public static final String ENABLED = ".startOnLoad";
private static final String PROP_KEYSTORE_PASSWORD = "routerconsole.keystorePassword";
private static final String DEFAULT_KEYSTORE_PASSWORD = "changeit";
private static final String PROP_KEY_PASSWORD = "routerconsole.keyPassword";
private static final String DEFAULT_LISTEN_PORT = "7657";
private static final String DEFAULT_LISTEN_HOST = "127.0.0.1";
private static final String DEFAULT_WEBAPPS_DIR = "./webapps/";
private static final String USAGE = "Bad RouterConsoleRunner arguments, check clientApp.0.args in your clients.config file! " +
"Usage: [[port host[,host]] [-s sslPort [host[,host]]] [webAppsDir]]";
static {
System.setProperty("org.mortbay.http.Version.paranoid", "true");
@@ -42,6 +59,27 @@ public class RouterConsoleRunner {
}
/**
* <pre>
* non-SSL:
* RouterConsoleRunner
* RouterConsoleRunner 7657
* RouterConsoleRunner 7657 127.0.0.1
* RouterConsoleRunner 7657 127.0.0.1,::1
* RouterConsoleRunner 7657 127.0.0.1,::1 ./webapps/
*
* SSL:
* RouterConsoleRunner -s 7657
* RouterConsoleRunner -s 7657 127.0.0.1
* RouterConsoleRunner -s 7657 127.0.0.1,::1
* RouterConsoleRunner -s 7657 127.0.0.1,::1 ./webapps/
*
* If using both, non-SSL must be first:
* RouterConsoleRunner 7657 127.0.0.1 -s 7667
* RouterConsoleRunner 7657 127.0.0.1 -s 7667 127.0.0.1
* RouterConsoleRunner 7657 127.0.0.1,::1 -s 7667 127.0.0.1,::1
* RouterConsoleRunner 7657 127.0.0.1,::1 -s 7667 127.0.0.1,::1 ./webapps/
* </pre>
*
* @param args second arg may be a comma-separated list of bind addresses,
* for example ::1,127.0.0.1
* On XP, the other order (127.0.0.1,::1) fails the IPV6 bind,
@@ -50,10 +88,40 @@ public class RouterConsoleRunner {
* So the wise choice is ::1,127.0.0.1
*/
public RouterConsoleRunner(String args[]) {
if (args.length == 3) {
_listenPort = args[0].trim();
_listenHost = args[1].trim();
_webAppsDir = args[2].trim();
if (args.length == 0) {
// _listenHost and _webAppsDir are defaulted below
_listenPort = DEFAULT_LISTEN_PORT;
} else {
boolean ssl = false;
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-s"))
ssl = true;
else if ((!ssl) && _listenPort == null)
_listenPort = args[i];
else if ((!ssl) && _listenHost == null)
_listenHost = args[i];
else if (ssl && _sslListenPort == null)
_sslListenPort = args[i];
else if (ssl && _sslListenHost == null)
_sslListenHost = args[i];
else if (_webAppsDir == null)
_webAppsDir = args[i];
else {
System.err.println(USAGE);
throw new IllegalArgumentException(USAGE);
}
}
}
if (_listenHost == null)
_listenHost = DEFAULT_LISTEN_HOST;
if (_sslListenHost == null)
_sslListenHost = _listenHost;
if (_webAppsDir == null)
_webAppsDir = DEFAULT_WEBAPPS_DIR;
// _listenPort and _sslListenPort are not defaulted, if one or the other is null, do not enable
if (_listenPort == null && _sslListenPort == null) {
System.err.println(USAGE);
throw new IllegalArgumentException(USAGE);
}
}
@@ -74,6 +142,18 @@ public class RouterConsoleRunner {
// so Jetty can find WebAppConfiguration
System.setProperty("jetty.class.path", I2PAppContext.getGlobalContext().getBaseDir() + "/lib/routerconsole.jar");
_server = new Server();
String log = I2PAppContext.getGlobalContext().getProperty("routerconsole.log");
if (log != null) {
File logFile = new File(log);
if (!logFile.isAbsolute())
logFile = new File(I2PAppContext.getGlobalContext().getLogDir(), "logs/" + log);
try {
_server.setRequestLog(new NCSARequestLog(logFile.getAbsolutePath()));
} catch (IOException ioe) {
System.err.println("ERROR: Unable to create Jetty log: " + ioe);
}
}
boolean rewrite = false;
Properties props = webAppProperties();
if (props.isEmpty()) {
@@ -96,27 +176,69 @@ public class RouterConsoleRunner {
List<String> notStarted = new ArrayList();
WebApplicationHandler baseHandler = null;
try {
StringTokenizer tok = new StringTokenizer(_listenHost, " ,");
int boundAddresses = 0;
while (tok.hasMoreTokens()) {
String host = tok.nextToken().trim();
try {
if (host.indexOf(":") >= 0) // IPV6 - requires patched Jetty 5
_server.addListener('[' + host + "]:" + _listenPort);
else
_server.addListener(host + ':' + _listenPort);
boundAddresses++;
} catch (IOException ioe) { // this doesn't seem to work, exceptions don't happen until start() below
System.err.println("Unable to bind routerconsole to " + host + " port " + _listenPort + ' ' + ioe);
// add standard listeners
if (_listenPort != null) {
StringTokenizer tok = new StringTokenizer(_listenHost, " ,");
while (tok.hasMoreTokens()) {
String host = tok.nextToken().trim();
try {
if (host.indexOf(":") >= 0) // IPV6 - requires patched Jetty 5
_server.addListener('[' + host + "]:" + _listenPort);
else
_server.addListener(host + ':' + _listenPort);
boundAddresses++;
} catch (IOException ioe) { // this doesn't seem to work, exceptions don't happen until start() below
System.err.println("Unable to bind routerconsole to " + host + " port " + _listenPort + ' ' + ioe);
}
}
}
// add SSL listeners
int sslPort = 0;
if (_sslListenPort != null) {
try {
sslPort = Integer.parseInt(_sslListenPort);
} catch (NumberFormatException nfe) {}
if (sslPort <= 0)
System.err.println("Bad routerconsole SSL port " + _sslListenPort);
}
if (sslPort > 0) {
I2PAppContext ctx = I2PAppContext.getGlobalContext();
File keyStore = new File(ctx.getConfigDir(), "keystore/console.ks");
if (verifyKeyStore(keyStore)) {
StringTokenizer tok = new StringTokenizer(_sslListenHost, " ,");
while (tok.hasMoreTokens()) {
String host = tok.nextToken().trim();
// doing it this way means we don't have to escape an IPv6 host with []
InetAddrPort iap = new InetAddrPort(host, sslPort);
try {
SslListener ssll = new SslListener(iap);
// the keystore path and password
ssll.setKeystore(keyStore.getAbsolutePath());
ssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD));
// the X.509 cert password (if not present, verifyKeyStore() returned false)
ssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork"));
_server.addListener(ssll);
boundAddresses++;
} catch (Exception e) { // probably no exceptions at this point
System.err.println("Unable to bind routerconsole to " + host + " port " + sslPort + " for SSL: " + e);
}
}
} else {
System.err.println("Unable to create or access keystore for SSL: " + keyStore.getAbsolutePath());
}
}
if (boundAddresses <= 0) {
System.err.println("Unable to bind routerconsole to any address on port " + _listenPort);
System.err.println("Unable to bind routerconsole to any address on port " + _listenPort + (sslPort > 0 ? (" or SSL port " + sslPort) : ""));
return;
}
_server.setRootWebApp(ROUTERCONSOLE);
WebApplicationContext wac = _server.addWebApplication("/", _webAppsDir + ROUTERCONSOLE + ".war");
File tmpdir = new SecureDirectory(workDir, ROUTERCONSOLE + "-" + _listenPort);
File tmpdir = new SecureDirectory(workDir, ROUTERCONSOLE + "-" +
(_listenPort != null ? _listenPort : _sslListenPort));
tmpdir.mkdir();
wac.setTempDirectory(tmpdir);
baseHandler = new LocaleWebAppHandler(I2PAppContext.getGlobalContext());
@@ -131,7 +253,8 @@ public class RouterConsoleRunner {
String enabled = props.getProperty(PREFIX + appName + ENABLED);
if (! "false".equals(enabled)) {
String path = new File(dir, fileNames[i]).getCanonicalPath();
tmpdir = new SecureDirectory(workDir, appName + "-" + _listenPort);
tmpdir = new SecureDirectory(workDir, appName + "-" +
(_listenPort != null ? _listenPort : _sslListenPort));
WebAppStarter.addWebApp(I2PAppContext.getGlobalContext(), _server, appName, path, tmpdir);
if (enabled == null) {
@@ -201,6 +324,90 @@ public class RouterConsoleRunner {
}
}
/**
* @return success if it exists and we have a password, or it was created successfully.
* @since 0.8.3
*/
private static boolean verifyKeyStore(File ks) {
if (ks.exists()) {
I2PAppContext ctx = I2PAppContext.getGlobalContext();
boolean rv = ctx.getProperty(PROP_KEY_PASSWORD) != null;
if (!rv)
System.err.println("Console SSL error, must set " + PROP_KEY_PASSWORD + " in " + (new File(ctx.getConfigDir(), "router.config")).getAbsolutePath());
return rv;
}
File dir = ks.getParentFile();
if (!dir.exists()) {
File sdir = new SecureDirectory(dir.getAbsolutePath());
if (!sdir.mkdir())
return false;
}
return createKeyStore(ks);
}
/**
* Call out to keytool to create a new keystore with a keypair in it.
* Trying to do this programatically is a nightmare, requiring either BouncyCastle
* libs or using proprietary Sun libs, and it's a huge mess.
*
* @return success
* @since 0.8.3
*/
private static boolean createKeyStore(File ks) {
I2PAppContext ctx = I2PAppContext.getGlobalContext();
// make a random 48 character password (30 * 8 / 5)
byte[] rand = new byte[30];
ctx.random().nextBytes(rand);
String keyPassword = Base32.encode(rand);
// and one for the cname
ctx.random().nextBytes(rand);
String cname = Base32.encode(rand) + ".console.i2p.net";
String keytool = (new File(System.getProperty("java.home"), "bin/keytool")).getAbsolutePath();
String[] args = new String[] {
keytool,
"-genkey", // -genkeypair preferred in newer keytools, but this works with more
"-storetype", KeyStore.getDefaultType(),
"-keystore", ks.getAbsolutePath(),
"-storepass", DEFAULT_KEYSTORE_PASSWORD,
"-alias", "console",
"-dname", "CN=" + cname + ",OU=Console,O=I2P Anonymous Network,L=XX,ST=XX,C=XX",
"-validity", "3652", // 10 years
"-keyalg", "DSA",
"-keysize", "1024",
"-keypass", keyPassword};
boolean success = (new ShellCommand()).executeSilentAndWaitTimed(args, 30); // 30 secs
if (success) {
success = ks.exists();
if (success) {
SecureFileOutputStream.setPerms(ks);
try {
RouterContext rctx = (RouterContext) ctx;
rctx.router().setConfigSetting(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD);
rctx.router().setConfigSetting(PROP_KEY_PASSWORD, keyPassword);
rctx.router().saveConfig();
} catch (Exception e) {} // class cast exception
}
}
if (success) {
System.err.println("Created self-signed certificate for " + cname + " in keystore: " + ks.getAbsolutePath() + "\n" +
"The certificate name was generated randomly, and is not associated with your " +
"IP address, host name, router identity, or destination keys.");
} else {
System.err.println("Failed to create console SSL keystore using command line:");
StringBuilder buf = new StringBuilder(256);
for (int i = 0; i < args.length; i++) {
buf.append('"').append(args[i]).append("\" ");
}
System.err.println(buf.toString());
System.err.println("This is for the Sun/Oracle keytool, others may be incompatible.\n" +
"If you create the keystore manually, you must add " + PROP_KEYSTORE_PASSWORD + " and " + PROP_KEY_PASSWORD +
" to " + (new File(ctx.getConfigDir(), "router.config")).getAbsolutePath());
}
return success;
}
static void initialize(WebApplicationContext context) {
String password = getPassword();
if (password != null) {

View File

@@ -1,8 +1,11 @@
package net.i2p.router.web;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
@@ -15,10 +18,12 @@ import net.i2p.router.RouterVersion;
import net.i2p.util.EepGet;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.PartialEepGet;
import net.i2p.util.VersionComparator;
/**
* <p>Handles the request to update the router by firing off an
* {@link net.i2p.util.EepGet} call to download the latest signed update file
* <p>Handles the request to update the router by firing one or more
* {@link net.i2p.util.EepGet} calls to download the latest signed update file
* and displaying the status to anyone who asks.
* </p>
* <p>After the download completes the signed update file is verified with
@@ -125,6 +130,11 @@ public class UpdateHandler {
protected boolean done;
protected EepGet _get;
protected final DecimalFormat _pct = new DecimalFormat("0.0%");
/** tells the listeners what mode we are in */
private boolean _isPartial;
/** set by the listeners on completion */
private boolean _isNewer;
private ByteArrayOutputStream _baos;
public UpdateRunner() {
_isRunning = false;
@@ -141,39 +151,88 @@ public class UpdateHandler {
System.setProperty(PROP_UPDATE_IN_PROGRESS, "false");
_isRunning = false;
}
/**
* Loop through the entire list of update URLs.
* For each one, first get the version from the first 56 bytes and see if
* it is newer than what we are running now.
* If it is, get the whole thing.
*/
protected void update() {
updateStatus("<b>" + _("Updating") + "</b>");
// TODO:
// Do a PartialEepGet on the selected URL, check for version we expect,
// and loop if it isn't what we want.
// This will allow us to do a release without waiting for the last host to install the update.
// Alternative: In bytesTransferred(), Check the data in the output file after
// we've received at least 56 bytes. Need a cancel() method in EepGet ?
String updateURL = selectUpdateURL();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Selected update URL: " + updateURL);
boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
int proxyPort = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_PORT, ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT);
try {
if (shouldProxy)
// 40 retries!!
_get = new EepGet(_context, proxyHost, proxyPort, 40, _updateFile, updateURL, false);
else
_get = new EepGet(_context, 1, _updateFile, updateURL, false);
_get.addStatusListener(UpdateRunner.this);
_get.fetch();
} catch (Throwable t) {
_log.error("Error updating", t);
List<String> urls = getUpdateURLs();
if (urls.isEmpty()) {
// not likely, don't bother translating
updateStatus("<b>Update source list is empty, cannot download update</b>");
_log.log(Log.CRIT, "Update source list is empty - cannot download update");
return;
}
if (shouldProxy)
_baos = new ByteArrayOutputStream(TrustedUpdate.HEADER_BYTES);
for (String updateURL : urls) {
updateStatus("<b>" + _("Updating from {0}", linkify(updateURL)) + "</b>");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Selected update URL: " + updateURL);
// Check the first 56 bytes for the version
if (shouldProxy) {
_isPartial = true;
_isNewer = false;
_baos.reset();
try {
// no retries
_get = new PartialEepGet(_context, proxyHost, proxyPort, _baos, updateURL, TrustedUpdate.HEADER_BYTES);
_get.addStatusListener(UpdateRunner.this);
_get.fetch();
} catch (Throwable t) {
_isNewer = false;
}
_isPartial = false;
if (!_isNewer)
continue;
}
// Now get the whole thing
try {
if (shouldProxy)
// 40 retries!!
_get = new EepGet(_context, proxyHost, proxyPort, 40, _updateFile, updateURL, false);
else
_get = new EepGet(_context, 1, _updateFile, updateURL, false);
_get.addStatusListener(UpdateRunner.this);
_get.fetch();
} catch (Throwable t) {
_log.error("Error updating", t);
}
if (this.done)
break;
}
}
// EepGet Listeners below.
// We use the same for both the partial and the full EepGet,
// with a couple of adjustments depending on which mode.
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {
_isNewer = false;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Attempt failed on " + url, cause);
// ignored
}
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {
if (_isPartial)
return;
StringBuilder buf = new StringBuilder(64);
buf.append("<b>").append(_("Updating")).append("</b> ");
double pct = ((double)alreadyTransferred + (double)currentWrite) /
@@ -186,6 +245,19 @@ public class UpdateHandler {
updateStatus(buf.toString());
}
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
if (_isPartial) {
// Compare version with what we have now
String newVersion = TrustedUpdate.getVersionString(new ByteArrayInputStream(_baos.toByteArray()));
boolean newer = (new VersionComparator()).compare(newVersion, RouterVersion.VERSION) > 0;
if (!newer) {
updateStatus("<b>" + _("No new version found at {0}", linkify(url)) + "</b>");
if (_log.shouldLog(Log.WARN))
_log.warn("Found old version \"" + newVersion + "\" at " + url);
}
_isNewer = newer;
return;
}
// Process the .sud/.su2 file
updateStatus("<b>" + _("Update downloaded") + "</b>");
TrustedUpdate up = new TrustedUpdate(_context);
File f = new File(_updateFile);
@@ -223,15 +295,16 @@ public class UpdateHandler {
}
} else {
_log.log(Log.CRIT, err + " from " + url);
updateStatus("<b>" + err + ' ' + _("from {0}", url) + " </b>");
updateStatus("<b>" + err + ' ' + _("from {0}", linkify(url)) + " </b>");
}
}
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
_isNewer = false;
// don't display bytesTransferred as it is meaningless
_log.log(Log.CRIT, "Update from " + url + " did not download completely (" +
_log.error("Update from " + url + " did not download completely (" +
bytesRemaining + " remaining after " + currentAttempt + " tries)");
updateStatus("<b>" + _("Transfer failed") + "</b>");
updateStatus("<b>" + _("Transfer failed from {0}", linkify(url)) + "</b>");
}
public void headerReceived(String url, int attemptNum, String key, String val) {}
public void attempting(String url) {}
@@ -242,27 +315,24 @@ public class UpdateHandler {
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
}
private String selectUpdateURL() {
private List<String> getUpdateURLs() {
String URLs = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_URL, ConfigUpdateHandler.DEFAULT_UPDATE_URL);
StringTokenizer tok = new StringTokenizer(URLs, " ,\r\n");
List URLList = new ArrayList();
List<String> URLList = new ArrayList();
while (tok.hasMoreTokens())
URLList.add(tok.nextToken().trim());
int size = URLList.size();
//_log.log(Log.DEBUG, "Picking update source from " + size + " candidates.");
if (size <= 0) {
_log.log(Log.CRIT, "Update source list is empty - cannot download update");
return null;
}
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
_log.log(Log.DEBUG, "Picked update source " + index + ".");
return (String) URLList.get(index);
Collections.shuffle(URLList, _context.random());
return URLList;
}
protected void updateStatus(String s) {
_status = s;
}
protected static String linkify(String url) {
return "<a target=\"_blank\" href=\"" + url + "\"/>" + url + "</a>";
}
/** translate a string */
protected String _(String s) {
return Messages.getString(s, _context);

View File

@@ -31,7 +31,7 @@
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigAdvancedHandler.nonce")%>" >
<input type="hidden" name="action" value="blah" >
<h3><%=intl._("Advanced I2P Configuration")%></h3>
<textarea rows="32" cols="60" name="config" wrap="off"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br><hr>
<textarea rows="32" cols="60" name="config" wrap="off" spellcheck="false"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br><hr>
<div class="formaction">
<input type="reset" value="<%=intl._("Cancel")%>" >
<input type="submit" name="shouldsave" value="<%=intl._("Save changes")%>" >

View File

@@ -47,7 +47,51 @@ button span.hide{
<input type="submit" name="edit" value="<%=intl._("Add Client")%>" />
<% } %>
<input type="submit" name="action" value="<%=intl._("Save Client Configuration")%>" />
</div></div><h3><a name="webapp"></a><%=intl._("WebApp Configuration")%></h3><p>
</div></div>
<h3><a name="i2cp"></a><%=intl._("Advanced Client Interface Configuration")%></h3><p>
<b><%=intl._("External I2CP (I2P Client Protocol) Interface Configuration")%></b><br>
<input type="radio" class="optbox" name="mode" value="1" <%=clientshelper.i2cpModeChecked(1) %> >
<%=intl._("Enabled without SSL")%><br>
<input type="radio" class="optbox" name="mode" value="2" <%=clientshelper.i2cpModeChecked(2) %> >
<%=intl._("Enabled with SSL required")%><br>
<input type="radio" class="optbox" name="mode" value="0" <%=clientshelper.i2cpModeChecked(0) %> >
<%=intl._("Disabled - Clients outside this Java process may not connect")%><br>
<%=intl._("I2CP Port")%>:
<input name="port" type="text" size="5" maxlength="5" value="<jsp:getProperty name="clientshelper" property="port" />" ><br>
<%=intl._("I2CP Interface")%>:
<select name="interface">
<%
String[] ips = clientshelper.intfcAddresses();
for (int i = 0; i < ips.length; i++) {
out.print("<option value=\"");
out.print(ips[i]);
out.print('\"');
if (clientshelper.isIFSelected(ips[i]))
out.print(" selected=\"selected\"");
out.print('>');
out.print(ips[i]);
out.print("</option>\n");
}
%>
</select><br>
<b><%=intl._("Authorization")%></b><br>
<input type="checkbox" class="optbox" name="auth" value="true" <jsp:getProperty name="clientshelper" property="auth" /> >
<%=intl._("Require username and password")%><br>
<%=intl._("Username")%>:
<input name="user" type="text" value="<jsp:getProperty name="clientshelper" property="user" />" ><br>
<%=intl._("Password")%>:
<input name="pw" type="password" value="<jsp:getProperty name="clientshelper" property="pw" />" ><br>
</p><p><b><%=intl._("The default settings will work for most people.")%></b>
<%=intl._("Any changes made here must also be configured in the external client.")%>
<%=intl._("Many clients do not support SSL or authorization.")%>
<i><%=intl._("All changes require restart to take effect.")%></i>
</p><hr><div class="formaction">
<input type="submit" name="foo" value="<%=intl._("Cancel")%>" />
<input type="submit" name="action" value="<%=intl._("Save Interface Configuration")%>" />
</div>
<h3><a name="webapp"></a><%=intl._("WebApp Configuration")%></h3><p>
<%=intl._("The Java web applications listed below are started by the webConsole client and run in the same JVM as the router. They are usually web applications accessible through the router console. They may be complete applications (e.g. i2psnark),front-ends to another client or application which must be separately enabled (e.g. susidns, i2ptunnel), or have no web interface at all (e.g. addressbook).")%>
</p><p>
<%=intl._("A web app may also be disabled by removing the .war file from the webapps directory; however the .war file and web app will reappear when you update your router to a newer version, so disabling the web app here is the preferred method.")%>

View File

@@ -38,7 +38,7 @@
<div class="wideload">
<p><table><tr>
<td class="mediumtags" align="right"><%=intl._("Dest. name, hash, or full key")%>:</td>
<td><textarea name="peer" cols="44" rows="1" style="height: 3em;" wrap="off"></textarea></td>
<td><textarea name="peer" cols="44" rows="1" style="height: 3em;" wrap="off" spellcheck="false"></textarea></td>
</tr><tr>
<td class="mediumtags" align="right"><%=intl._("Encryption Key")%>:</td>
<td><input type="text" size="55" name="key" ></td>

View File

@@ -0,0 +1,59 @@
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<%@include file="css.jsi" %>
<%=intl.title("config reseeding")%>
</head><body>
<%@include file="summary.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigReseedHelper" id="reseedHelper" scope="request" />
<jsp:setProperty name="reseedHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<h1><%=intl._("I2P Reseeding Configuration")%></h1>
<div class="main" id="main">
<%@include file="confignav.jsi" %>
<jsp:useBean class="net.i2p.router.web.ConfigReseedHandler" id="formhandler" scope="request" />
<% formhandler.storeMethod(request.getMethod()); %>
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" />
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
<jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
<jsp:getProperty name="formhandler" property="allMessages" />
<div class="configure"><form action="" method="POST">
<% String prev = System.getProperty("net.i2p.router.web.ConfigReseedHandler.nonce");
if (prev != null) System.setProperty("net.i2p.router.web.ConfigReseedHandler.noncePrev", prev);
System.setProperty("net.i2p.router.web.ConfigReseedHandler.nonce", new java.util.Random().nextLong()+""); %>
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigReseedHandler.nonce")%>" >
<h3><%=intl._("Reseeding Configuration")%></h3>
<p><%=intl._("Reseeding is the bootstrapping process used to find other routers when you first install I2P, or when your router has too few router references remaining.")%>
<%=intl._("If reseeding has failed, you should first check your network connection.")%>
<p><b><%=intl._("The default settings will work for most people.")%></b>
<%=intl._("Change these only if HTTP is blocked by a restrictive firewall, reseed has failed, and you have access to an HTTP proxy.")%>
<%=intl._("See {0} for instructions on reseeding manually.", "<a href=\"http://www.i2p2.de/faq.html#manual_reseed\">" + intl._("the FAQ") + "</a>")%>
</p>
<div class="wideload">
<table border="0" cellspacing="5">
<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URL Selection")%></b></td>
<td><input type="radio" class="optbox" name="mode" value="0" <%=reseedHelper.modeChecked(0) %> >
<%=intl._("Try SSL first then non-SSL")%>
<input type="radio" class="optbox" name="mode" value="1" <%=reseedHelper.modeChecked(1) %> >
<%=intl._("Use SSL only")%>
<input type="radio" class="optbox" name="mode" value="2" <%=reseedHelper.modeChecked(2) %> >
<%=intl._("Use non-SSL only")%></td></tr>
<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URLs")%></b></td>
<td><textarea name="reseedURL" wrap="off" spellcheck="false"><jsp:getProperty name="reseedHelper" property="reseedURL" /></textarea></td></tr>
<tr><td class="mediumtags" align="right"><b><%=intl._("Enable HTTP proxy (not used for SSL)")%></b></td>
<td><input type="checkbox" class="optbox" name="enable" value="true" <jsp:getProperty name="reseedHelper" property="enable" /> ></td></tr>
<tr><td class="mediumtags" align="right"><b><%=intl._("HTTP Proxy Host")%>:</b></td>
<td><input name="host" type="text" value="<jsp:getProperty name="reseedHelper" property="host" />" ></td></tr>
<tr><td class="mediumtags" align="right"><b><%=intl._("HTTP Proxy Port")%>:</b></td>
<td><input name="port" type="text" value="<jsp:getProperty name="reseedHelper" property="port" />" ></td></tr>
</table></div>
<hr><div class="formaction">
<input type="submit" name="foo" value="<%=intl._("Cancel")%>" />
<input type="submit" name="action" value="<%=intl._("Save changes and reseed now")%>" />
<input type="submit" name="action" value="<%=intl._("Save changes")%>" />
</div></form></div></div></body></html>

View File

@@ -50,9 +50,9 @@
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("eepProxy port")%>:</b></td>
<td><input type="text" size="4" name="proxyPort" value="<jsp:getProperty name="updatehelper" property="proxyPort" />" /></td>
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Update URLs")%>:</b></td>
<td><textarea name="updateURL" wrap="off"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td>
<td><textarea name="updateURL" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td>
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Trusted keys")%>:</b></td>
<td><textarea name="trustedKeys" wrap="off"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td>
<td><textarea name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td>
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Update with unsigned development builds?")%></b></td>
<td><jsp:getProperty name="updatehelper" property="updateUnsigned" /></td>
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Unsigned Build URL")%>:</b></td>

View File

@@ -0,0 +1,63 @@
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
// Let's make this easy...
final Integer ERROR_CODE = (Integer) request.getAttribute(org.mortbay.jetty.servlet.ServletHandler.__J_S_ERROR_STATUS_CODE);
final String ERROR_URI = (String) request.getAttribute(org.mortbay.jetty.servlet.ServletHandler.__J_S_ERROR_REQUEST_URI);
final String ERROR_MESSAGE = (String) request.getAttribute(org.mortbay.jetty.servlet.ServletHandler.__J_S_ERROR_MESSAGE);
final Class ERROR_CLASS = (Class)request.getAttribute(org.mortbay.jetty.servlet.ServletHandler.__J_S_ERROR_EXCEPTION_TYPE);
final Throwable ERROR_THROWABLE = (Throwable)request.getAttribute(org.mortbay.jetty.servlet.ServletHandler.__J_S_ERROR_EXCEPTION);
if (ERROR_CODE != null && ERROR_MESSAGE != null) {
// this is deprecated but we don't want sendError()
response.setStatus(ERROR_CODE.intValue(), ERROR_MESSAGE);
}
%>
<html><head>
<%@include file="css.jsi" %>
<%=intl.title("Internal Error")%>
</head><body>
<div class="routersummaryouter">
<div class="routersummary">
<a href="/" title="<%=intl._("Router Console")%>"><img src="/themes/console/images/i2plogo.png" alt="<%=intl._("I2P Router Console")%>" border="0"></a><hr>
<a href="/config"><%=intl._("Configuration")%></a> <a href="/help"><%=intl._("Help")%></a>
</div></div>
<h1><%=ERROR_CODE%> <%=ERROR_MESSAGE%></h1>
<div class="sorry" id="warning">
<%=intl._("Sorry! There has been an internal error.")%>
<hr>
<p>
<% /* note to translators - both parameters are URLs */
%><%=intl._("Please report bugs on {0} or {1}.",
"<a href=\"http://trac.i2p2.i2p/newticket\">trac.i2p2.i2p</a>",
"<a href=\"http://trac.i2p2.de/newticket\">trac.i2p2.de</a>")%>
<%=intl._("You may use the username \"guest\" and password \"guest\" if you do not wish to register.")%>
<p><%=intl._("Please include this information in bug reports")%>:
</p></div><div class="sorry" id="warning2">
<h3><%=intl._("Error Details")%></h3>
<p>
<%=intl._("Error {0}", ERROR_CODE)%>: <%=ERROR_URI%> <%=ERROR_MESSAGE%>
</p><p>
<%
if (ERROR_THROWABLE != null) {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(2048);
java.io.PrintStream ps = new java.io.PrintStream(baos);
ERROR_THROWABLE.printStackTrace(ps);
ps.close();
String trace = baos.toString();
trace = trace.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
trace = trace.replace("\n", "<br>&nbsp;&nbsp;&nbsp;&nbsp;\n");
out.print(trace);
}
%>
</p>
<h3><%=intl._("I2P Version and Running Environment")%></h3>
<p>
<b>I2P version:</b> <%=net.i2p.router.RouterVersion.FULL_VERSION%><br>
<b>Java version:</b> <%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%> (<%=System.getProperty("java.runtime.name")%> <%=System.getProperty("java.runtime.version")%>)<br>
<b>Platform:</b> <%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br>
<b>Processor:</b> <%=net.i2p.util.NativeBigInteger.cpuModel()%> (<%=net.i2p.util.NativeBigInteger.cpuType()%>)<br>
<b>Jbigi:</b> <%=net.i2p.util.NativeBigInteger.loadStatus()%><br>
<b>Encoding:</b> <%=System.getProperty("file.encoding")%></p>
<p><%=intl._("Note that system information, log timestamps, and log messages may provide clues to your location; please review everything you include in a bug report.")%></p>
</div></body></html>

View File

@@ -15,11 +15,27 @@ boolean rendered = false;
String c = request.getParameter("c");
if (c != null && c.length() > 0) {
java.io.OutputStream cout = response.getOutputStream();
response.setContentType("image/png");
response.setHeader("Cache-Control", "max-age=86400"); // cache for a day
String base = net.i2p.I2PAppContext.getGlobalContext().getBaseDir().getAbsolutePath();
String file = "docs" + java.io.File.separatorChar + "icons" + java.io.File.separatorChar +
"flags" + java.io.File.separatorChar + c + ".png";
java.io.File ffile = new java.io.File(base, file);
long lastmod = ffile.lastModified();
if (lastmod > 0) {
long iflast = request.getDateHeader("If-Modified-Since");
// iflast is -1 if not present; round down file time
if (iflast >= ((lastmod / 1000) * 1000)) {
response.sendError(304, "Not Modified");
return;
}
response.setDateHeader("Last-Modified", lastmod);
// cache for a day
response.setDateHeader("Expires", net.i2p.I2PAppContext.getGlobalContext().clock().now() + 86400000l);
response.setHeader("Cache-Control", "public, max-age=86400");
}
long length = ffile.length();
if (length > 0)
response.setHeader("Content-Length", Long.toString(length));
response.setContentType("image/png");
try {
net.i2p.util.FileUtil.readFile(file, base, cout);
rendered = true;

View File

@@ -174,7 +174,7 @@ details on other applications available, as well as their licenses, please see t
client applications can be found on our <a href="http://www.i2p2.i2p/download">download page</a>.
.</p>
<h2>Release history</h2>
<h2>Change Log</h2>
<jsp:useBean class="net.i2p.router.web.ContentHelper" id="contenthelper" scope="request" />
<% java.io.File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getBaseDir(), "history.txt"); %>
<jsp:setProperty name="contenthelper" property="page" value="<%=fpath.getAbsolutePath()%>" />
@@ -182,6 +182,5 @@ client applications can be found on our <a href="http://www.i2p2.i2p/download">d
<jsp:setProperty name="contenthelper" property="startAtBeginning" value="true" />
<jsp:getProperty name="contenthelper" property="textContent" />
<p>A more complete list of changes can be found
in the history.txt file in your i2p directory.
<p><a href="/history.txt">View the full change log</a>
</p><hr></div></body></html>

View File

@@ -9,7 +9,7 @@
<%@include file="summary.jsi" %>
<h1><%=intl._("I2P Router Logs")%></h1>
<div class="main" id="main">
<div class="joblog"><h3><%=intl._("I2P Version & Running Environment")%></h3><a name="version"> </a>
<div class="joblog"><h3><%=intl._("I2P Version and Running Environment")%></h3><a name="version"> </a>
<p>
<% /* note to translators - both parameters are URLs */
%><%=intl._("Please report bugs on {0} or {1}.",

View File

@@ -0,0 +1,16 @@
<%
/*
* USE CAUTION WHEN EDITING
* Trailing whitespace OR NEWLINE on the last line will cause
* IllegalStateExceptions !!!
*
* Do not tag this file for translation.
*/
response.setContentType("text/plain");
String base = net.i2p.I2PAppContext.getGlobalContext().getBaseDir().getAbsolutePath();
try {
net.i2p.util.FileUtil.readFile("history.txt", base, response.getOutputStream());
} catch (java.io.IOException ioe) {
response.sendError(403, ioe.toString());
}
%>

View File

@@ -19,7 +19,6 @@ if (uri.endsWith(".css")) {
} else if (uri.endsWith(".ico")) {
response.setContentType("image/x-icon");
}
response.setHeader("Cache-Control", "max-age=86400"); // cache for a day
/*
* User or plugin themes
* If the request is for /themes/console/foo/bar/baz,
@@ -44,5 +43,26 @@ if (themePath != null)
else
base = net.i2p.I2PAppContext.getGlobalContext().getBaseDir().getAbsolutePath() +
java.io.File.separatorChar + "docs";
net.i2p.util.FileUtil.readFile(uri, base, response.getOutputStream());
java.io.File file = new java.io.File(base, uri);
long lastmod = file.lastModified();
if (lastmod > 0) {
long iflast = request.getDateHeader("If-Modified-Since");
// iflast is -1 if not present; round down file time
if (iflast >= ((lastmod / 1000) * 1000)) {
response.sendError(304, "Not Modified");
return;
}
response.setDateHeader("Last-Modified", lastmod);
// cache for a day
response.setDateHeader("Expires", net.i2p.I2PAppContext.getGlobalContext().clock().now() + 86400000l);
response.setHeader("Cache-Control", "public, max-age=86400");
}
long length = file.length();
if (length > 0)
response.setHeader("Content-Length", Long.toString(length));
try {
net.i2p.util.FileUtil.readFile(uri, base, response.getOutputStream());
} catch (java.io.IOException ioe) {
response.sendError(403, ioe.toString());
}
%>

View File

@@ -17,6 +17,11 @@
<url-pattern>/javadoc/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>net.i2p.router.web.jsp.viewhistory_jsp</servlet-name>
<url-pattern>/history.txt</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
@@ -30,4 +35,8 @@
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error500.jsp</location>
</error-page>
</web-app>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -15,8 +15,9 @@ class I2PServerSocketFull implements I2PServerSocket {
}
/**
* Warning, unlike regular ServerSocket, may return null
*
* @return I2PSocket
* @return I2PSocket OR NULL
* @throws net.i2p.I2PException
* @throws SocketTimeoutException
*/

View File

@@ -114,7 +114,7 @@ public class I2PSocketManagerFull implements I2PSocketManager {
/**
*
* @return connected I2PSocket
* @return connected I2PSocket OR NULL
* @throws net.i2p.I2PException
* @throws java.net.SocketTimeoutException
*/

View File

@@ -497,7 +497,7 @@ class MessageOutputStream extends OutputStream {
if (ws.writeFailed())
throw new IOException("Flush available failed");
else if (!ws.writeAccepted())
throw new InterruptedIOException("Flush available timed out");
throw new InterruptedIOException("Flush available timed out (" + _writeTimeout + "ms)");
}
long afterAccept = System.currentTimeMillis();
if ( (afterAccept - afterBuild > 1000) && (_log.shouldLog(Log.DEBUG)) )

View File

@@ -6,10 +6,8 @@
<!--
<property name="javac.compilerargs" value="-warn:-unchecked,raw,unused,serial" />
-->
<!-- Add Apache Harmony's Pack200 library if you don't have java.util.jar.Pack200
See core/java/src/net/i2p/util/FileUtil.java for code changes required
to use this library instead of Sun's version.
Or to comment it all out if you don't have either.
<!-- Additional classpath. No longer required; we find pack200 classes at runtime.
See core/java/src/net/i2p/util/FileUtil.java for more info.
-->
<!--
<property name="javac.classpath" value="/PATH/TO/pack200.jar" />
@@ -239,7 +237,7 @@
splitindex="true"
doctitle="I2P Javadocs for Release ${release.number} Build ${build.number}"
windowtitle="I2P Anonymous Network - Java Documentation - Version ${release.number}">
<group title="Core SDK (i2p.jar)" packages="net.i2p:net.i2p.*:net.i2p.client:net.i2p.client.*:freenet.support.CPUInformation:org.bouncycastle.crypto:org.bouncycastle.crypto.*:gnu.crypto.*:gnu.gettext:org.xlattice.crypto.filters:com.nettgryppa.security" />
<group title="Core SDK (i2p.jar)" packages="net.i2p:net.i2p.*:net.i2p.client:net.i2p.client.*:net.i2p.internal:net.i2p.internal.*:freenet.support.CPUInformation:org.bouncycastle.crypto:org.bouncycastle.crypto.*:gnu.crypto.*:gnu.gettext:org.xlattice.crypto.filters:com.nettgryppa.security" />
<group title="Streaming Library" packages="net.i2p.client.streaming" />
<group title="Router" packages="net.i2p.router:net.i2p.router.*:net.i2p.data.i2np:org.cybergarage.*:org.freenetproject" />
<group title="Router Console" packages="net.i2p.router.web" />
@@ -757,7 +755,7 @@
</target>
<target name="findbugs" depends="build2">
<echo message="Starting findbugs, this will take a while..." />
<exec executable="nice">
<exec executable="nice" failonerror="true">
<arg value="findbugs"/>
<arg value="-textui"/>
<arg value="-projectName"/>
@@ -765,9 +763,9 @@
<arg value="-sortByClass"/>
<arg value="-xml"/>
<arg value="-output"/>
<arg value="findbugs.xml"/>
<arg value="i2p.fba"/>
<arg value="-auxclasspath"/>
<arg value="build/commons-el.jar:build/commons-logging.jar:build/jasper-compiler.jar:build/jasper-runtime.jar:build/javax.servlet.jar:build/org.mortbay.jetty.jar:apps/jrobin/jrobin-1.4.0.jar:apps/systray/java/lib/systray4j.jar:installer/lib/wrapper/linux/wrapper.jar"/>
<arg value="build/commons-el.jar:build/commons-logging.jar:build/jasper-compiler.jar:build/jasper-runtime.jar:build/javax.servlet.jar:build/org.mortbay.jetty.jar:apps/jrobin/jrobin-1.4.0.jar:apps/systray/java/lib/systray4j.jar:installer/lib/wrapper/linux/wrapper.jar:apps/susidns/src/WEB-INF/lib/standard.jar:apps/susidns/src/WEB-INF/lib/jstl.jar:apps/jrobin/jrobin-1.4.0.jar"/>
<arg value="-sourcepath"/>
<arg value="apps/BOB/src/:apps/addressbook/java/src/:apps/i2psnark/java/src/:apps/i2ptunnel/java/src/:apps/ministreaming/java/src/:apps/routerconsole/java/src/:apps/sam/java/src/:apps/streaming/java/src/:apps/susidns/src/java/src/:apps/susimail/src/src/:apps/systray/java/src/:core/java/src/:router/java/src/"/>
<!-- start of the files to be analyzed -->
@@ -781,15 +779,16 @@
<arg value="build/jbigi.jar"/>
<arg value="build/mstreaming.jar"/>
<arg value="build/router.jar/"/>
<!-- use the class files rather than the jar for routerconsole so we don't analyze jrobin -->
<arg value="apps/routerconsole/java/build/obj/"/>
<arg value="build/routerconsole.jar"/>
<arg value="build/routerconsole.war"/>
<arg value="build/sam.jar"/>
<arg value="build/streaming.jar"/>
<arg value="build/susidns.war"/>
<arg value="build/susimail.war"/>
<arg value="build/systray.jar"/>
</exec>
<echo message="Findbugs output stored in findbugs.xml" />
<echo message="Findbugs output stored in i2p.fba" />
<echo message="Now run: findbugs i2p.fba" />
</target>
<target name="buildWithDesktopgui" depends="buildrouter,builddepSmall">
<ant dir="apps/desktopgui" target="build_jar" />

View File

@@ -1,5 +1,6 @@
/*
* Created on Jul 14, 2004
* Updated on Jan 8, 2011
*/
package freenet.support.CPUInformation;
@@ -129,11 +130,26 @@ public class CPUID {
CPUIDResult c = doCPUID(1);
return c.EAX & 0xf;
}
private static int getCPUFlags()
private static int getEDXCPUFlags()
{
CPUIDResult c = doCPUID(1);
return c.EDX;
}
private static int getECXCPUFlags()
{
CPUIDResult c = doCPUID(1);
return c.ECX;
}
private static int getExtendedEDXCPUFlags()
{
CPUIDResult c = doCPUID(0x80000001);
return c.EDX;
}
private static int getExtendedECXCPUFlags()
{
CPUIDResult c = doCPUID(0x80000001);
return c.ECX;
}
//Returns a CPUInfo item for the current type of CPU
//If I could I would declare this method in a interface named
@@ -163,13 +179,25 @@ public class CPUID {
return getCPUVendorID();
}
public boolean hasMMX(){
return (getCPUFlags() & 0x800000) >0; //Bit 23
return (getEDXCPUFlags() & 0x800000) >0; //EDX Bit 23
}
public boolean hasSSE(){
return (getCPUFlags() & 0x2000000) >0; //Bit 25
return (getEDXCPUFlags() & 0x2000000) >0; //EDX Bit 25
}
public boolean hasSSE2(){
return (getCPUFlags() & 0x4000000) >0; //Bit 26
return (getEDXCPUFlags() & 0x4000000) >0; //EDX Bit 26
}
public boolean hasSSE3(){
return (getEDXCPUFlags() & 0x1) >0; //ECX Bit 0
}
public boolean hasSSE41(){
return (getEDXCPUFlags() & 0x80000) >0; //ECX Bit 19
}
public boolean hasSSE42(){
return (getEDXCPUFlags() & 0x100000) >0; //ECX Bit 20
}
public boolean hasSSE4A(){
return (getExtendedECXCPUFlags() & 0x40) >0; //Extended ECX Bit 6
}
public boolean IsC3Compatible() { return false; }
}
@@ -296,77 +324,119 @@ public class CPUID {
return getCPUFamily() > 6 || (getCPUFamily() == 6 && getCPUModel() >=3);
}
public boolean IsPentium3Compatible()
{
return getCPUFamily() > 6 || (getCPUFamily() == 6 && getCPUModel() >=7);
{
// Atom
if (getCPUExtendedModel() == 1 && (getCPUFamily() == 6 && (getCPUModel() == 12))){
return true;
// ??
} else if (getCPUExtendedModel() == 0 && (getCPUFamily() > 6 || (getCPUFamily() == 6 && getCPUModel() >=7))){
return true;
} else {
return false;
}
}
public boolean IsPentium4Compatible()
{
return getCPUFamily() >= 15;
{
// P4
if (getCPUFamily() >= 15){
return true;
// Xeon MP (45nm) or Core i7
} else if (getCPUExtendedModel() == 1 && (getCPUFamily() == 6 && (getCPUModel() == 10 || getCPUModel() == 13))){
return true;
// Core 2 Duo
} else if (getCPUExtendedModel() == 0 && getCPUFamily() == 6 && getCPUModel() == 15){
return true;
} else {
return false;
}
}
public String getCPUModelString() throws UnknownCPUException {
if(getCPUFamily() == 4){
switch(getCPUModel()){
case 0:
return "486 DX-25/33";
case 1:
return "486 DX-50";
case 2:
return "486 SX";
case 3:
return "486 DX/2";
case 4:
return "486 SL";
case 5:
return "486 SX/2";
case 7:
return "486 DX/2-WB";
case 8:
return "486 DX/4";
case 9:
return "486 DX/4-WB";
}
}
if(getCPUFamily() == 5){
switch(getCPUModel()){
case 0:
return "Pentium 60/66 A-step";
case 1:
return "Pentium 60/66";
case 2:
return "Pentium 75 - 200";
case 3:
return "OverDrive PODP5V83";
case 4:
return "Pentium MMX";
case 7:
return "Mobile Pentium 75 - 200";
case 8:
return "Mobile Pentium MMX";
}
if (getCPUExtendedModel() == 0){
if(getCPUFamily() == 4){
switch(getCPUModel()){
case 0:
return "486 DX-25/33";
case 1:
return "486 DX-50";
case 2:
return "486 SX";
case 3:
return "486 DX/2";
case 4:
return "486 SL";
case 5:
return "486 SX/2";
case 7:
return "486 DX/2-WB";
case 8:
return "486 DX/4";
case 9:
return "486 DX/4-WB";
}
}
}
if (getCPUExtendedModel() == 0){
if(getCPUFamily() == 5){
switch(getCPUModel()){
case 0:
return "Pentium 60/66 A-step";
case 1:
return "Pentium 60/66";
case 2:
return "Pentium 75 - 200";
case 3:
return "OverDrive PODP5V83";
case 4:
return "Pentium MMX";
case 7:
return "Mobile Pentium 75 - 200";
case 8:
return "Mobile Pentium MMX";
}
}
}
if(getCPUFamily() == 6){
switch(getCPUModel()){
case 0:
return "Pentium Pro A-step";
case 1:
return "Pentium Pro";
case 3:
return "Pentium II (Klamath)";
case 5:
return "Pentium II (Deschutes), Celeron (Covington), Mobile Pentium II (Dixon)";
case 6:
return "Mobile Pentium II, Celeron (Mendocino)";
case 7:
return "Pentium III (Katmai)";
case 8:
return "Pentium III (Coppermine), Celeron w/SSE";
case 9:
return "Mobile Pentium III";
case 10:
return "Pentium III Xeon (Cascades)";
case 11:
return "Pentium III (130 nm)";
}
if (getCPUExtendedModel() == 0){
switch(getCPUModel()){
case 0:
return "Pentium Pro A-step";
case 1:
return "Pentium Pro";
case 3:
return "Pentium II (Klamath)";
case 5:
return "Pentium II (Deschutes), Celeron (Covington), Mobile Pentium II (Dixon)";
case 6:
return "Mobile Pentium II, Celeron (Mendocino)";
case 7:
return "Pentium III (Katmai)";
case 8:
return "Pentium III (Coppermine), Celeron w/SSE";
case 9:
return "Mobile Pentium III (Banias)";
case 10:
return "Pentium III Xeon (Cascades)";
case 11:
return "Pentium III (130 nm)";
case 13:
return "Mobile Pentium III (Dothan)";
case 14:
return "Mobile Core (Yonah)";
case 15:
return "Core 2 (Conroe)";
}
} else {
if (getCPUExtendedModel() == 1){
switch(getCPUModel()){
case 10:
return "Core i7";
case 12:
return "Atom";
case 13:
return "Xeon MP";
}
}
}
}
if(getCPUFamily() == 7){
switch(getCPUModel()){
@@ -384,6 +454,10 @@ public class CPUID {
return "Pentium IV (130 nm)";
case 3:
return "Pentium IV (90 nm)";
case 4:
return "Pentium IV (90 nm)";
case 6:
return "Pentium IV (65 nm)";
}
}
if(getCPUExtendedFamily() == 1){
@@ -407,7 +481,7 @@ public class CPUID {
System.out.println("CPU Family: " + getCPUFamily());
System.out.println("CPU Model: " + getCPUModel());
System.out.println("CPU Stepping: " + getCPUStepping());
System.out.println("CPU Flags: " + getCPUFlags());
System.out.println("CPU Flags: " + getEDXCPUFlags());
CPUInfo c = getInfo();
System.out.println(" **More CPUInfo**");
@@ -415,6 +489,10 @@ public class CPUID {
System.out.println(" CPU has MMX: " + c.hasMMX());
System.out.println(" CPU has SSE: " + c.hasSSE());
System.out.println(" CPU has SSE2: " + c.hasSSE2());
System.out.println(" CPU has SSE3: " + c.hasSSE3());
System.out.println(" CPU has SSE4.1: " + c.hasSSE41());
System.out.println(" CPU has SSE4.2: " + c.hasSSE42());
System.out.println(" CPU has SSE4A: " + c.hasSSE4A());
if(c instanceof IntelCPUInfo){
System.out.println(" **Intel-info**");
System.out.println(" Is pII-compatible: "+((IntelCPUInfo)c).IsPentium2Compatible());

View File

@@ -1,6 +1,6 @@
/*
* Created on Jul 16, 2004
*
* Created on Jul 14, 2004
* Updated on Jan 8, 2011
*/
package freenet.support.CPUInformation;
@@ -42,5 +42,25 @@ public interface CPUInfo
*/
public boolean hasSSE2();
/**
* @return true iff the CPU support the SSE3 instruction set.
*/
public boolean hasSSE3();
/**
* @return true iff the CPU support the SSE4.1 instruction set.
*/
public boolean hasSSE41();
/**
* @return true iff the CPU support the SSE4.2 instruction set.
*/
public boolean hasSSE42();
/**
* @return true iff the CPU support the SSE4A instruction set.
*/
public boolean hasSSE4A();
public boolean IsC3Compatible();
}

View File

@@ -168,6 +168,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
//System.out.println("Refilling " + (++refillCount) + " after " + diff + " for the PRNG took " + refillTime);
}
/*****
public static void main(String args[]) {
try {
AsyncFortunaStandalone rand = new AsyncFortunaStandalone(null); // Will cause NPEs above; fix this if you want to test! Sorry...
@@ -195,4 +196,5 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
} catch (Exception e) { e.printStackTrace(); }
try { Thread.sleep(5*60*1000); } catch (InterruptedException ie) {}
}
*****/
}

View File

@@ -351,6 +351,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
}
}
/*****
public static void main(String args[]) {
byte in[] = new byte[16];
byte out[] = new byte[16];
@@ -379,7 +380,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
long after = System.currentTimeMillis();
System.out.println("encrypting 4MB took " + (after-beforeAll));
} catch (Exception e) { e.printStackTrace(); }
/*
****/ /*
FortunaStandalone f = new FortunaStandalone();
java.util.HashMap props = new java.util.HashMap();
byte initSeed[] = new byte[1234];
@@ -394,5 +395,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
long time = System.currentTimeMillis() - before;
System.out.println("512MB took " + time + ", or " + (8*64d)/((double)time/1000d) +"MBps");
*/
/*****
}
*****/
}

View File

@@ -16,7 +16,7 @@ package net.i2p;
public class CoreVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = "0.8.2";
public final static String VERSION = "0.8.3";
public static void main(String args[]) {
System.out.println("I2P Core version: " + VERSION);

View File

@@ -3,6 +3,7 @@ package net.i2p;
import java.io.File;
import java.util.HashSet;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import net.i2p.client.naming.NamingService;
@@ -21,7 +22,9 @@ import net.i2p.crypto.KeyGenerator;
import net.i2p.crypto.SHA256Generator;
import net.i2p.crypto.SessionKeyManager;
import net.i2p.crypto.TransientSessionKeyManager;
import net.i2p.data.Base64;
import net.i2p.data.RoutingKeyGenerator;
import net.i2p.internal.InternalClientManager;
import net.i2p.stat.StatManager;
import net.i2p.util.Clock;
import net.i2p.util.ConcurrentHashSet;
@@ -363,10 +366,12 @@ public class I2PAppContext {
if (_tmpDir == null) {
String d = getProperty("i2p.dir.temp", System.getProperty("java.io.tmpdir"));
// our random() probably isn't warmed up yet
String f = "i2p-" + Math.abs((new java.util.Random()).nextInt()) + ".tmp";
byte[] rand = new byte[6];
(new Random()).nextBytes(rand);
String f = "i2p-" + Base64.encode(rand) + ".tmp";
_tmpDir = new SecureDirectory(d, f);
if (_tmpDir.exists()) {
// good or bad ?
// good or bad ? loop and try again?
} else if (_tmpDir.mkdir()) {
_tmpDir.deleteOnExit();
} else {
@@ -843,4 +848,13 @@ public class I2PAppContext {
public boolean isRouterContext() {
return false;
}
/**
* Use this to connect to the router in the same JVM.
* @return always null in I2PAppContext, the client manager if in RouterContext
* @since 0.8.3
*/
public InternalClientManager internalClientManager() {
return null;
}
}

View File

@@ -22,6 +22,6 @@ class BWLimitsMessageHandler extends HandlerImpl {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Handle message " + message);
BandwidthLimitsMessage msg = (BandwidthLimitsMessage) message;
((I2PSimpleSession)session).bwReceived(msg.getLimits());
session.bwReceived(msg.getLimits());
}
}

View File

@@ -9,6 +9,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.data.i2cp.I2CPMessage;
import net.i2p.data.i2cp.I2CPMessageImpl;
import net.i2p.data.i2cp.I2CPMessageException;
import net.i2p.internal.PoisonI2CPMessage;
import net.i2p.util.I2PAppThread;
/**
@@ -50,7 +51,7 @@ class ClientWriterRunner implements Runnable {
public void stopWriting() {
_messagesToWrite.clear();
try {
_messagesToWrite.put(new PoisonMessage());
_messagesToWrite.put(new PoisonI2CPMessage());
} catch (InterruptedException ie) {}
}
@@ -62,7 +63,7 @@ class ClientWriterRunner implements Runnable {
} catch (InterruptedException ie) {
continue;
}
if (msg.getType() == PoisonMessage.MESSAGE_TYPE)
if (msg.getType() == PoisonI2CPMessage.MESSAGE_TYPE)
break;
// only thread, we don't need synchronized
try {
@@ -80,18 +81,4 @@ class ClientWriterRunner implements Runnable {
}
_messagesToWrite.clear();
}
/**
* End-of-stream msg used to stop the concurrent queue
* See http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
*
*/
private static class PoisonMessage extends I2CPMessageImpl {
public static final int MESSAGE_TYPE = 999999;
public int getType() {
return MESSAGE_TYPE;
}
public void doReadMessage(InputStream buf, int size) throws I2CPMessageException, IOException {}
public byte[] doWriteMessage() throws I2CPMessageException, IOException { return null; }
}
}

View File

@@ -10,6 +10,9 @@ import net.i2p.data.i2cp.I2CPMessage;
import net.i2p.data.i2cp.DestReplyMessage;
import net.i2p.util.Log;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
/**
* Handle I2CP dest replies from the router
*/
@@ -22,6 +25,14 @@ class DestReplyMessageHandler extends HandlerImpl {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Handle message " + message);
DestReplyMessage msg = (DestReplyMessage) message;
((I2PSimpleSession)session).destReceived(msg.getDestination());
Destination d = msg.getDestination();
if (d != null) {
session.destReceived(d);
} else {
Hash h = msg.getHash();
if (h != null)
session.destLookupFailed(h);
}
// else let it time out
}
}

View File

@@ -0,0 +1,183 @@
package net.i2p.client;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.security.KeyStore;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
/**
* Loads trusted ASCII certs from ~/.i2p/certificates/ and $CWD/certificates/.
* Keeps a single static SSLContext for the whole JVM.
*
* @author zzz
* @since 0.8.3
*/
class I2CPSSLSocketFactory {
private static final Object _initLock = new Object();
private static SSLSocketFactory _factory;
private static Log _log;
private static final String CERT_DIR = "certificates";
/**
* Initializes the static SSL Context if required, then returns a socket
* to the host.
*
* @param ctx just for logging
* @throws IOException on init error or usual socket errors
*/
public static Socket createSocket(I2PAppContext ctx, String host, int port) throws IOException {
synchronized(_initLock) {
if (_factory == null) {
_log = ctx.logManager().getLog(I2CPSSLSocketFactory.class);
initSSLContext(ctx);
if (_factory == null)
throw new IOException("Unable to create SSL Context for I2CP Client");
_log.info("I2CP Client-side SSL Context initialized");
}
}
return _factory.createSocket(host, port);
}
/**
* Loads certs from
* the ~/.i2p/certificates/ and $CWD/certificates/ directories.
*/
private static void initSSLContext(I2PAppContext context) {
KeyStore ks;
try {
ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, "".toCharArray());
} catch (GeneralSecurityException gse) {
_log.error("Key Store init error", gse);
return;
} catch (IOException ioe) {
_log.error("Key Store init error", ioe);
return;
}
File dir = new File(context.getConfigDir(), CERT_DIR);
int adds = addCerts(dir, ks);
int totalAdds = adds;
if (adds > 0 && _log.shouldLog(Log.INFO))
_log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath());
File dir2 = new File(System.getProperty("user.dir"), CERT_DIR);
if (!dir.getAbsolutePath().equals(dir2.getAbsolutePath())) {
adds = addCerts(dir2, ks);
totalAdds += adds;
if (adds > 0 && _log.shouldLog(Log.INFO))
_log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath());
}
if (totalAdds > 0) {
if (_log.shouldLog(Log.INFO))
_log.info("Loaded total of " + totalAdds + " new trusted certificates");
} else {
_log.error("No trusted certificates loaded (looked in " +
dir.getAbsolutePath() + (dir.getAbsolutePath().equals(dir2.getAbsolutePath()) ? "" : (" and " + dir2.getAbsolutePath())) +
", I2CP SSL client connections will fail. " +
"Copy the file certificates/i2cp.local.crt from the router to the directory.");
// don't continue, since we didn't load the system keystore, we have nothing.
return;
}
try {
SSLContext sslc = SSLContext.getInstance("TLS");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
sslc.init(null, tmf.getTrustManagers(), context.random());
_factory = sslc.getSocketFactory();
} catch (GeneralSecurityException gse) {
_log.error("SSL context init error", gse);
}
}
/**
* Load all X509 Certs from a directory and add them to the
* trusted set of certificates in the key store
*
* @return number successfully added
*/
private static int addCerts(File dir, KeyStore ks) {
if (_log.shouldLog(Log.INFO))
_log.info("Looking for X509 Certificates in " + dir.getAbsolutePath());
int added = 0;
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (!f.isFile())
continue;
// use file name as alias
String alias = f.getName().toLowerCase();
boolean success = addCert(f, alias, ks);
if (success)
added++;
}
}
}
return added;
}
/**
* Load an X509 Cert from a file and add it to the
* trusted set of certificates in the key store
*
* @return success
*/
private static boolean addCert(File file, String alias, KeyStore ks) {
InputStream fis = null;
try {
fis = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
if (_log.shouldLog(Log.INFO)) {
_log.info("Read X509 Certificate from " + file.getAbsolutePath() +
" Issuer: " + cert.getIssuerX500Principal() +
"; Valid From: " + cert.getNotBefore() +
" To: " + cert.getNotAfter());
}
try {
cert.checkValidity();
} catch (CertificateExpiredException cee) {
_log.error("Rejecting expired X509 Certificate: " + file.getAbsolutePath(), cee);
return false;
} catch (CertificateNotYetValidException cnyve) {
_log.error("Rejecting X509 Certificate not yet valid: " + file.getAbsolutePath(), cnyve);
return false;
}
ks.setCertificateEntry(alias, cert);
if (_log.shouldLog(Log.INFO))
_log.info("Now trusting X509 Certificate, Issuer: " + cert.getIssuerX500Principal());
} catch (GeneralSecurityException gse) {
_log.error("Error reading X509 Certificate: " + file.getAbsolutePath(), gse);
return false;
} catch (IOException ioe) {
_log.error("Error reading X509 Certificate: " + file.getAbsolutePath(), ioe);
return false;
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
return true;
}
}

View File

@@ -10,6 +10,8 @@ package net.i2p.client;
*/
import net.i2p.I2PAppContext;
import net.i2p.data.i2cp.BandwidthLimitsMessage;
import net.i2p.data.i2cp.DestReplyMessage;
import net.i2p.data.i2cp.DisconnectMessage;
import net.i2p.data.i2cp.MessagePayloadMessage;
import net.i2p.data.i2cp.MessageStatusMessage;
@@ -36,6 +38,8 @@ class I2PClientMessageHandlerMap {
highest = Math.max(highest, MessagePayloadMessage.MESSAGE_TYPE);
highest = Math.max(highest, MessageStatusMessage.MESSAGE_TYPE);
highest = Math.max(highest, SetDateMessage.MESSAGE_TYPE);
highest = Math.max(highest, DestReplyMessage.MESSAGE_TYPE);
highest = Math.max(highest, BandwidthLimitsMessage.MESSAGE_TYPE);
_handlers = new I2CPMessageHandler[highest+1];
_handlers[DisconnectMessage.MESSAGE_TYPE] = new DisconnectMessageHandler(context);
@@ -44,6 +48,8 @@ class I2PClientMessageHandlerMap {
_handlers[MessagePayloadMessage.MESSAGE_TYPE] = new MessagePayloadMessageHandler(context);
_handlers[MessageStatusMessage.MESSAGE_TYPE] = new MessageStatusMessageHandler(context);
_handlers[SetDateMessage.MESSAGE_TYPE] = new SetDateMessageHandler(context);
_handlers[DestReplyMessage.MESSAGE_TYPE] = new DestReplyMessageHandler(context);
_handlers[BandwidthLimitsMessage.MESSAGE_TYPE] = new BWLimitsMessageHandler(context);
}
public I2CPMessageHandler getHandler(int messageTypeId) {

View File

@@ -138,13 +138,21 @@ public interface I2PSession {
public SigningPrivateKey getPrivateKey();
/**
* Lookup up a Hash
*
* Lookup a Destination by Hash.
* Blocking. Waits a max of 10 seconds by default.
*/
public Destination lookupDest(Hash h) throws I2PSessionException;
/**
* Get the current bandwidth limits
* Blocking.
* @param maxWait ms
* @since 0.8.3
* @return null on failure
*/
public Destination lookupDest(Hash h, long maxWait) throws I2PSessionException;
/**
* Get the current bandwidth limits. Blocking.
*/
public int[] bandwidthLimits() throws I2PSessionException;

View File

@@ -15,7 +15,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
@@ -23,6 +22,8 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.I2PAppContext;
import net.i2p.data.DataFormatException;
@@ -33,14 +34,18 @@ import net.i2p.data.PrivateKey;
import net.i2p.data.SessionKey;
import net.i2p.data.SessionTag;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.i2cp.DestLookupMessage;
import net.i2p.data.i2cp.GetBandwidthLimitsMessage;
import net.i2p.data.i2cp.GetDateMessage;
import net.i2p.data.i2cp.I2CPMessage;
import net.i2p.data.i2cp.I2CPMessageException;
import net.i2p.data.i2cp.I2CPMessageReader;
import net.i2p.data.i2cp.MessagePayloadMessage;
import net.i2p.data.i2cp.SessionId;
import net.i2p.util.I2PThread;
import net.i2p.util.InternalSocket;
import net.i2p.internal.I2CPMessageQueue;
import net.i2p.internal.InternalClientManager;
import net.i2p.internal.QueuedI2CPMessageReader;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
@@ -66,9 +71,9 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
/** currently granted lease set, or null */
private LeaseSet _leaseSet;
/** hostname of router */
/** hostname of router - will be null if in RouterContext */
protected String _hostname;
/** port num to router */
/** port num to router - will be 0 if in RouterContext */
protected int _portNum;
/** socket for comm */
protected Socket _socket;
@@ -79,6 +84,13 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
/** where we pipe our messages */
protected /* FIXME final FIXME */OutputStream _out;
/**
* Used for internal connections to the router.
* If this is set, _socket, _writer, and _out will be null.
* @since 0.8.3
*/
protected I2CPMessageQueue _queue;
/** who we send events to */
protected I2PSessionListener _sessionListener;
@@ -86,6 +98,11 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
protected I2CPMessageProducer _producer;
/** map of Long --> MessagePayloadMessage */
protected Map<Long, MessagePayloadMessage> _availableMessages;
/** hashes of lookups we are waiting for */
protected final LinkedBlockingQueue<LookupWaiter> _pendingLookups = new LinkedBlockingQueue();
protected final Object _bwReceivedLock = new Object();
protected int[] _bwLimits;
protected I2PClientMessageHandlerMap _handlerMap;
@@ -122,6 +139,9 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
private long _lastActivity;
private boolean _isReduced;
/** SSL interface (only) @since 0.8.3 */
protected static final String PROP_ENABLE_SSL = "i2cp.SSL";
void dateUpdated() {
_dateReceived = true;
synchronized (_dateReceivedLock) {
@@ -172,19 +192,24 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
protected void loadConfig(Properties options) {
_options = new Properties();
_options.putAll(filter(options));
_hostname = _options.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
String portNum = _options.getProperty(I2PClient.PROP_TCP_PORT, LISTEN_PORT + "");
try {
_portNum = Integer.parseInt(portNum);
} catch (NumberFormatException nfe) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + "Invalid port number specified, defaulting to "
+ LISTEN_PORT, nfe);
_portNum = LISTEN_PORT;
if (_context.isRouterContext()) {
// just for logging
_hostname = "[internal connection]";
} else {
_hostname = _options.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
String portNum = _options.getProperty(I2PClient.PROP_TCP_PORT, LISTEN_PORT + "");
try {
_portNum = Integer.parseInt(portNum);
} catch (NumberFormatException nfe) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + "Invalid port number specified, defaulting to "
+ LISTEN_PORT, nfe);
_portNum = LISTEN_PORT;
}
}
// auto-add auth if required, not set in the options, and we are in the same JVM
if (_context.isRouterContext() &&
// auto-add auth if required, not set in the options, and we are not in the same JVM
if ((!_context.isRouterContext()) &&
Boolean.valueOf(_context.getProperty("i2cp.auth")).booleanValue() &&
((!options.containsKey("i2cp.username")) || (!options.containsKey("i2cp.password")))) {
String configUser = _context.getProperty("i2cp.username");
@@ -272,10 +297,6 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
setOpening(true);
_closed = false;
_availabilityNotifier.stopNotifying();
I2PThread notifier = new I2PThread(_availabilityNotifier);
notifier.setName("Notifier " + _myDestination.calculateHash().toBase64().substring(0,4));
notifier.setDaemon(true);
notifier.start();
if ( (_options != null) &&
(I2PClient.PROP_RELIABILITY_GUARANTEED.equals(_options.getProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT))) ) {
@@ -285,17 +306,32 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
long startConnect = _context.clock().now();
try {
// If we are in the router JVM, connect using the interal pseudo-socket
_socket = InternalSocket.getSocket(_hostname, _portNum);
// _socket.setSoTimeout(1000000); // Uhmmm we could really-really use a real timeout, and handle it.
_out = _socket.getOutputStream();
synchronized (_out) {
_out.write(I2PClient.PROTOCOL_BYTE);
_out.flush();
// If we are in the router JVM, connect using the interal queue
if (_context.isRouterContext()) {
// _socket, _out, and _writer remain null
InternalClientManager mgr = _context.internalClientManager();
if (mgr == null)
throw new I2PSessionException("Router is not ready for connections");
// the following may throw an I2PSessionException
_queue = mgr.connect();
_reader = new QueuedI2CPMessageReader(_queue, this);
} else {
if (Boolean.valueOf(_options.getProperty(PROP_ENABLE_SSL)).booleanValue())
_socket = I2CPSSLSocketFactory.createSocket(_context, _hostname, _portNum);
else
_socket = new Socket(_hostname, _portNum);
// _socket.setSoTimeout(1000000); // Uhmmm we could really-really use a real timeout, and handle it.
_out = _socket.getOutputStream();
synchronized (_out) {
_out.write(I2PClient.PROTOCOL_BYTE);
_out.flush();
}
_writer = new ClientWriterRunner(_out, this);
InputStream in = _socket.getInputStream();
_reader = new I2CPMessageReader(in, this);
}
_writer = new ClientWriterRunner(_out, this);
InputStream in = _socket.getInputStream();
_reader = new I2CPMessageReader(in, this);
Thread notifier = new I2PAppThread(_availabilityNotifier, "ClientNotifier " + getPrefix(), true);
notifier.start();
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "before startReading");
_reader.startReading();
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Before getDate");
@@ -435,6 +471,10 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
}
}
/**
* This notifies the client of payload messages.
* Needs work.
*/
protected class AvailabilityNotifier implements Runnable {
private List _pendingIds;
private List _pendingSizes;
@@ -497,8 +537,9 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
}
/**
* Recieve notification of some I2CP message and handle it if possible
*
* The I2CPMessageEventListener callback.
* Recieve notification of some I2CP message and handle it if possible.
* @param reader unused
*/
public void messageReceived(I2CPMessageReader reader, I2CPMessage message) {
I2CPMessageHandler handler = _handlerMap.getHandler(message.getType());
@@ -515,7 +556,9 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
}
/**
* Recieve notifiation of an error reading the I2CP stream
* The I2CPMessageEventListener callback.
* Recieve notifiation of an error reading the I2CP stream.
* @param reader unused
* @param error non-null
*/
public void readError(I2CPMessageReader reader, Exception error) {
@@ -567,9 +610,14 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
* @throws I2PSessionException if the message is malformed or there is an error writing it out
*/
void sendMessage(I2CPMessage message) throws I2PSessionException {
if (isClosed() || _writer == null)
if (isClosed())
throw new I2PSessionException("Already closed");
_writer.addMessage(message);
else if (_queue != null)
_queue.offer(message); // internal
else if (_writer == null)
throw new I2PSessionException("Already closed");
else
_writer.addMessage(message);
}
/**
@@ -581,8 +629,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
// Only log as WARN if the router went away
int level;
String msgpfx;
if ((error instanceof EOFException) ||
(error.getMessage() != null && error.getMessage().startsWith("Pipe closed"))) {
if (error instanceof EOFException) {
level = Log.WARN;
msgpfx = "Router closed connection: ";
} else {
@@ -631,7 +678,9 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
_log.warn("Error destroying the session", ipe);
}
}
_availabilityNotifier.stopNotifying();
// SimpleSession does not initialize
if (_availabilityNotifier != null)
_availabilityNotifier.stopNotifying();
_closed = true;
_closing = false;
closeSocket();
@@ -649,6 +698,10 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
_reader.stopReading();
_reader = null;
}
if (_queue != null) {
// internal
_queue.close();
}
if (_writer != null) {
_writer.stopWriting();
_writer = null;
@@ -666,7 +719,9 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
}
/**
* Recieve notification that the I2CP connection was disconnected
* The I2CPMessageEventListener callback.
* Recieve notification that the I2CP connection was disconnected.
* @param reader unused
*/
public void disconnected(I2CPMessageReader reader) {
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Disconnected", new Exception("Disconnected"));
@@ -733,21 +788,113 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
buf.append(s);
else
buf.append(getClass().getSimpleName());
buf.append(" #");
if (_sessionId != null)
buf.append(_sessionId.getSessionId());
else
buf.append("n/a");
buf.append(" #").append(_sessionId.getSessionId());
buf.append("]: ");
return buf.toString();
}
public Destination lookupDest(Hash h) throws I2PSessionException {
return null;
/** called by the message handler */
void destReceived(Destination d) {
Hash h = d.calculateHash();
for (LookupWaiter w : _pendingLookups) {
if (w.hash.equals(h)) {
w.destination = d;
synchronized (w) {
w.notifyAll();
}
}
}
}
/** called by the message handler */
void destLookupFailed(Hash h) {
for (LookupWaiter w : _pendingLookups) {
if (w.hash.equals(h)) {
synchronized (w) {
w.notifyAll();
}
}
}
}
/** called by the message handler */
void bwReceived(int[] i) {
_bwLimits = i;
synchronized (_bwReceivedLock) {
_bwReceivedLock.notifyAll();
}
}
/**
* Simple object to wait for lookup replies
* @since 0.8.3
*/
private static class LookupWaiter {
/** the request */
public final Hash hash;
/** the reply */
public Destination destination;
public LookupWaiter(Hash h) {
this.hash = h;
}
}
/**
* Blocking. Waits a max of 10 seconds by default.
* See lookupDest with maxWait parameter to change.
* Implemented in 0.8.3 in I2PSessionImpl;
* previously was available only in I2PSimpleSession.
* Multiple outstanding lookups are now allowed.
* @return null on failure
*/
public Destination lookupDest(Hash h) throws I2PSessionException {
return lookupDest(h, 10*1000);
}
/**
* Blocking.
* @param maxWait ms
* @since 0.8.3
* @return null on failure
*/
public Destination lookupDest(Hash h, long maxWait) throws I2PSessionException {
if (_closed)
return null;
LookupWaiter waiter = new LookupWaiter(h);
_pendingLookups.offer(waiter);
try {
sendMessage(new DestLookupMessage(h));
try {
synchronized (waiter) {
waiter.wait(maxWait);
}
} catch (InterruptedException ie) {}
} finally {
_pendingLookups.remove(waiter);
}
return waiter.destination;
}
/**
* Blocking. Waits a max of 5 seconds.
* But shouldn't take long.
* Implemented in 0.8.3 in I2PSessionImpl;
* previously was available only in I2PSimpleSession.
* Multiple outstanding lookups are now allowed.
* @return null on failure
*/
public int[] bandwidthLimits() throws I2PSessionException {
return null;
if (_closed)
return null;
sendMessage(new GetBandwidthLimitsMessage());
try {
synchronized (_bwReceivedLock) {
_bwReceivedLock.wait(5*1000);
}
} catch (InterruptedException ie) {}
return _bwLimits;
}
protected void updateActivity() {

View File

@@ -274,7 +274,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession {
_demultiplexer.messageAvailable(I2PSessionMuxedImpl.this,
msg.id, msg.size, msg.proto, msg.fromPort, msg.toPort);
} catch (Exception e) {
_log.error("Error notifying app of message availability");
_log.error("Error notifying app of message availability", e);
}
}
}

View File

@@ -19,8 +19,10 @@ import net.i2p.data.i2cp.DestLookupMessage;
import net.i2p.data.i2cp.DestReplyMessage;
import net.i2p.data.i2cp.GetBandwidthLimitsMessage;
import net.i2p.data.i2cp.I2CPMessageReader;
import net.i2p.util.I2PThread;
import net.i2p.util.InternalSocket;
import net.i2p.internal.I2CPMessageQueue;
import net.i2p.internal.InternalClientManager;
import net.i2p.internal.QueuedI2CPMessageReader;
import net.i2p.util.I2PAppThread;
/**
* Create a new session for doing naming and bandwidth queries only. Do not create a Destination.
@@ -31,12 +33,6 @@ import net.i2p.util.InternalSocket;
* @author zzz
*/
class I2PSimpleSession extends I2PSessionImpl2 {
private boolean _destReceived;
private /* FIXME final FIXME */ Object _destReceivedLock;
private Destination _destination;
private boolean _bwReceived;
private /* FIXME final FIXME */ Object _bwReceivedLock;
private int[] _bwLimits;
/**
* Create a new session for doing naming and bandwidth queries only. Do not create a destination.
@@ -44,12 +40,12 @@ class I2PSimpleSession extends I2PSessionImpl2 {
* @throws I2PSessionException if there is a problem
*/
public I2PSimpleSession(I2PAppContext context, Properties options) throws I2PSessionException {
// Warning, does not call super()
_context = context;
_log = context.logManager().getLog(I2PSimpleSession.class);
_handlerMap = new SimpleMessageHandlerMap(context);
_closed = true;
_closing = false;
_availabilityNotifier = new AvailabilityNotifier();
if (options == null)
options = System.getProperties();
loadConfig(options);
@@ -65,23 +61,32 @@ class I2PSimpleSession extends I2PSessionImpl2 {
@Override
public void connect() throws I2PSessionException {
_closed = false;
_availabilityNotifier.stopNotifying();
I2PThread notifier = new I2PThread(_availabilityNotifier);
notifier.setName("Simple Notifier");
notifier.setDaemon(true);
notifier.start();
try {
// If we are in the router JVM, connect using the interal pseudo-socket
_socket = InternalSocket.getSocket(_hostname, _portNum);
_out = _socket.getOutputStream();
synchronized (_out) {
_out.write(I2PClient.PROTOCOL_BYTE);
_out.flush();
// If we are in the router JVM, connect using the interal queue
if (_context.isRouterContext()) {
// _socket, _out, and _writer remain null
InternalClientManager mgr = _context.internalClientManager();
if (mgr == null)
throw new I2PSessionException("Router is not ready for connections");
// the following may throw an I2PSessionException
_queue = mgr.connect();
_reader = new QueuedI2CPMessageReader(_queue, this);
} else {
if (Boolean.valueOf(getOptions().getProperty(PROP_ENABLE_SSL)).booleanValue())
_socket = I2CPSSLSocketFactory.createSocket(_context, _hostname, _portNum);
else
_socket = new Socket(_hostname, _portNum);
_out = _socket.getOutputStream();
synchronized (_out) {
_out.write(I2PClient.PROTOCOL_BYTE);
_out.flush();
}
_writer = new ClientWriterRunner(_out, this);
InputStream in = _socket.getInputStream();
_reader = new I2CPMessageReader(in, this);
}
_writer = new ClientWriterRunner(_out, this);
InputStream in = _socket.getInputStream();
_reader = new I2CPMessageReader(in, this);
// we do not receive payload messages, so we do not need an AvailabilityNotifier
_reader.startReading();
} catch (UnknownHostException uhe) {
@@ -93,57 +98,6 @@ class I2PSimpleSession extends I2PSessionImpl2 {
}
}
/** called by the message handler */
void destReceived(Destination d) {
_destReceived = true;
_destination = d;
synchronized (_destReceivedLock) {
_destReceivedLock.notifyAll();
}
}
void bwReceived(int[] i) {
_bwReceived = true;
_bwLimits = i;
synchronized (_bwReceivedLock) {
_bwReceivedLock.notifyAll();
}
}
@Override
public Destination lookupDest(Hash h) throws I2PSessionException {
if (_closed)
return null;
_destReceivedLock = new Object();
sendMessage(new DestLookupMessage(h));
for (int i = 0; i < 10 && !_destReceived; i++) {
try {
synchronized (_destReceivedLock) {
_destReceivedLock.wait(1000);
}
} catch (InterruptedException ie) {}
}
_destReceived = false;
return _destination;
}
@Override
public int[] bandwidthLimits() throws I2PSessionException {
if (_closed)
return null;
_bwReceivedLock = new Object();
sendMessage(new GetBandwidthLimitsMessage());
for (int i = 0; i < 5 && !_bwReceived; i++) {
try {
synchronized (_bwReceivedLock) {
_bwReceivedLock.wait(1000);
}
} catch (InterruptedException ie) {}
}
_bwReceived = false;
return _bwLimits;
}
/**
* Only map message handlers that we will use
*/

View File

@@ -37,9 +37,9 @@ public final class I2PDatagramDissector {
private Hash rxHash = null;
private Signature rxSign = new Signature();
private Signature rxSign;
private Destination rxDest = new Destination();
private Destination rxDest;
private byte[] rxPayload = new byte[DGRAM_BUFSIZE];
@@ -68,6 +68,9 @@ public final class I2PDatagramDissector {
this.valid = false;
try {
rxDest = new Destination();
rxSign = new Signature();
// read destination
rxDest.readBytes(dgStream);
@@ -153,6 +156,8 @@ public final class I2PDatagramDissector {
* @return The Destination of the I2P repliable datagram sender
*/
public Destination extractSender() {
if (this.rxDest == null)
return null;
Destination retDest = new Destination();
try {
retDest.fromByteArray(this.rxDest.toByteArray());
@@ -184,6 +189,10 @@ public final class I2PDatagramDissector {
if(this.valid)
return;
if (rxSign == null || rxSign.getData() == null ||
rxDest == null || rxDest.getSigningPublicKey() == null)
throw new I2PInvalidDatagramException("Datagram not yet read");
// now validate
if (!this.dsaEng.verifySignature(rxSign, rxHash.getData(), rxDest.getSigningPublicKey()))
throw new I2PInvalidDatagramException("Incorrect I2P repliable datagram signature");

View File

@@ -22,6 +22,13 @@ import net.i2p.data.Hash;
*
* All calls are blocking and return null on failure.
* Timeout is set to 10 seconds in I2PSimpleSession.
*
* As of 0.8.3, standard I2PSessions support lookups,
* including multiple lookups in parallel, and overriding
* the default timeout.
* Using an existing I2PSession is much more efficient and
* flexible than using this class.
*
*/
class LookupDest {
@@ -47,7 +54,7 @@ class LookupDest {
/** @param h 32 byte hash */
static Destination lookupHash(I2PAppContext ctx, byte[] h) {
Hash key = new Hash(h);
Hash key = Hash.create(h);
Destination rv = null;
try {
I2PClient client = new I2PSimpleClient();

View File

@@ -22,13 +22,14 @@ import net.i2p.util.RandomSource;
* See CryptixAESEngine for the real thing.
*/
public class AESEngine {
private Log _log;
private I2PAppContext _context;
protected final Log _log;
protected final I2PAppContext _context;
public AESEngine(I2PAppContext ctx) {
_context = ctx;
_log = _context.logManager().getLog(AESEngine.class);
if (getClass() == AESEngine.class)
_log.warn("Warning: AES is disabled");
_log = _context.logManager().getLog(getClass());
if (getClass().equals(AESEngine.class))
_log.logAlways(Log.WARN, "AES is disabled");
}
/** Encrypt the payload with the session key
@@ -44,7 +45,10 @@ public class AESEngine {
encrypt(payload, payloadIndex, out, outIndex, sessionKey, iv, 0, length);
}
/** Encrypt the payload with the session key
/**
* Encrypt the payload with the session key.
* This just copies payload to out, see extension for the real thing.
*
* @param payload data to be encrypted
* @param payloadIndex index into the payload to start encrypting
* @param out where to store the result
@@ -55,7 +59,7 @@ public class AESEngine {
*/
public void encrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int ivOffset, int length) {
System.arraycopy(payload, payloadIndex, out, outIndex, length);
_log.warn("Warning: AES is disabled");
_log.logAlways(Log.WARN, "AES is disabled");
}
public byte[] safeEncrypt(byte payload[], SessionKey sessionKey, byte iv[], int paddedSize) {
@@ -118,7 +122,6 @@ public class AESEngine {
return data;
}
/** Decrypt the data with the session key
* @param payload data to be decrypted
* @param payloadIndex index into the payload to start decrypting
@@ -132,7 +135,10 @@ public class AESEngine {
decrypt(payload, payloadIndex, out, outIndex, sessionKey, iv, 0, length);
}
/** Decrypt the data with the session key
/**
* Decrypt the data with the session key.
* This just copies payload to out, see extension for the real thing.
*
* @param payload data to be decrypted
* @param payloadIndex index into the payload to start decrypting
* @param out where to store the cleartext
@@ -143,18 +149,20 @@ public class AESEngine {
*/
public void decrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int ivOffset, int length) {
System.arraycopy(payload, payloadIndex, out, outIndex, length);
_log.warn("Warning: AES is disabled");
_log.logAlways(Log.WARN, "AES is disabled");
}
/**
* Just copies payload to out
* This just copies payload to out, see extension for the real thing.
* @param sessionKey unused
*/
public void encryptBlock(byte payload[], int inIndex, SessionKey sessionKey, byte out[], int outIndex) {
System.arraycopy(payload, inIndex, out, outIndex, out.length - outIndex);
}
/** decrypt the data with the session key provided
/**
* This just copies payload to rv, see extension for the real thing.
*
* @param payload encrypted data
* @param sessionKey private session key
*/

View File

@@ -27,18 +27,16 @@ import net.i2p.util.Log;
* @author jrandom, thecrypto
*/
public class CryptixAESEngine extends AESEngine {
private Log _log;
private final static CryptixRijndael_Algorithm _algo = new CryptixRijndael_Algorithm();
private final static boolean USE_FAKE_CRYPTO = false;
private final static byte FAKE_KEY = 0x2A;
private CryptixAESKeyCache _cache;
// keys are now cached in the SessionKey objects
//private CryptixAESKeyCache _cache;
private static final ByteCache _prevCache = ByteCache.getInstance(16, 16);
public CryptixAESEngine(I2PAppContext context) {
super(context);
_log = context.logManager().getLog(CryptixAESEngine.class);
_cache = new CryptixAESKeyCache();
//_cache = new CryptixAESKeyCache();
}
/** @param length must be a multiple of 16 */

View File

@@ -8,6 +8,8 @@ import java.util.concurrent.LinkedBlockingQueue;
* data referenced in it is needed (which often is only one or two lines
* of code)
*
* Unused as a class, as the keys are cached in the SessionKey objects,
* but the static methods are used in FortunaStandalone.
*/
public final class CryptixAESKeyCache {
private final LinkedBlockingQueue<KeyCacheEntry> _availableKeys;
@@ -20,6 +22,9 @@ public final class CryptixAESKeyCache {
private static final int MAX_KEYS = 64;
/*
* @deprecated unused, keys are now cached in the SessionKey objects
*/
public CryptixAESKeyCache() {
_availableKeys = new LinkedBlockingQueue(MAX_KEYS);
}
@@ -27,6 +32,7 @@ public final class CryptixAESKeyCache {
/**
* Get the next available structure, either from the cache or a brand new one
*
* @deprecated unused, keys are now cached in the SessionKey objects
*/
public final KeyCacheEntry acquireKey() {
KeyCacheEntry rv = _availableKeys.poll();
@@ -38,6 +44,7 @@ public final class CryptixAESKeyCache {
/**
* Put this structure back onto the available cache for reuse
*
* @deprecated unused, keys are now cached in the SessionKey objects
*/
public final void releaseKey(KeyCacheEntry key) {
_availableKeys.offer(key);

View File

@@ -13,8 +13,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
@@ -48,14 +47,15 @@ import net.i2p.util.RandomSource;
* @author jrandom
*/
public class DHSessionKeyBuilder {
private static I2PAppContext _context = I2PAppContext.getGlobalContext();
private final static Log _log = new Log(DHSessionKeyBuilder.class);
private static int MIN_NUM_BUILDERS = -1;
private static int MAX_NUM_BUILDERS = -1;
private static int CALC_DELAY = -1;
/* FIXME this should be final if you syncronize FIXME */
private static volatile List _builders = new ArrayList(50);
private static Thread _precalcThread = null;
private static final I2PAppContext _context = I2PAppContext.getGlobalContext();
private static final Log _log;
private static final int MIN_NUM_BUILDERS;
private static final int MAX_NUM_BUILDERS;
private static final int CALC_DELAY;
private static final LinkedBlockingQueue<DHSessionKeyBuilder> _builders;
private static final Thread _precalcThread;
// the data of importance
private BigInteger _myPrivateValue;
private BigInteger _myPublicValue;
private BigInteger _peerValue;
@@ -65,17 +65,31 @@ public class DHSessionKeyBuilder {
public final static String PROP_DH_PRECALC_MIN = "crypto.dh.precalc.min";
public final static String PROP_DH_PRECALC_MAX = "crypto.dh.precalc.max";
public final static String PROP_DH_PRECALC_DELAY = "crypto.dh.precalc.delay";
public final static int DEFAULT_DH_PRECALC_MIN = 5;
public final static int DEFAULT_DH_PRECALC_MAX = 50;
public final static int DEFAULT_DH_PRECALC_DELAY = 10000;
public final static int DEFAULT_DH_PRECALC_MIN = 15;
public final static int DEFAULT_DH_PRECALC_MAX = 40;
public final static int DEFAULT_DH_PRECALC_DELAY = 200;
/** check every 30 seconds whether we have less than the minimum */
private static long _checkDelay = 30 * 1000;
static {
I2PAppContext ctx = _context;
ctx.statManager().createRateStat("crypto.dhGeneratePublicTime", "How long it takes to create x and X", "Encryption", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
ctx.statManager().createRateStat("crypto.dhCalculateSessionTime", "How long it takes to create the session key", "Encryption", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
MIN_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MIN, DEFAULT_DH_PRECALC_MIN);
MAX_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MAX, DEFAULT_DH_PRECALC_MAX);
_log = ctx.logManager().getLog(DHSessionKeyBuilder.class);
ctx.statManager().createRateStat("crypto.dhGeneratePublicTime", "How long it takes to create x and X", "Encryption", new long[] { 60*60*1000 });
ctx.statManager().createRateStat("crypto.dhCalculateSessionTime", "How long it takes to create the session key", "Encryption", new long[] { 60*60*1000 });
ctx.statManager().createRateStat("crypto.DHUsed", "Need a DH from the queue", "Encryption", new long[] { 60*60*1000 });
ctx.statManager().createRateStat("crypto.DHEmpty", "DH queue empty", "Encryption", new long[] { 60*60*1000 });
// add to the defaults for every 128MB of RAM, up to 512MB
long maxMemory = Runtime.getRuntime().maxMemory();
int factor = Math.min(4, (int) (1 + (maxMemory / (128*1024*1024l))));
int defaultMin = DEFAULT_DH_PRECALC_MIN * factor;
int defaultMax = DEFAULT_DH_PRECALC_MAX * factor;
MIN_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MIN, defaultMin);
MAX_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MAX, defaultMax);
CALC_DELAY = ctx.getProperty(PROP_DH_PRECALC_DELAY, DEFAULT_DH_PRECALC_DELAY);
_builders = new LinkedBlockingQueue(MAX_NUM_BUILDERS);
if (_log.shouldLog(Log.DEBUG))
_log.debug("DH Precalc (minimum: " + MIN_NUM_BUILDERS + " max: " + MAX_NUM_BUILDERS + ", delay: "
@@ -90,40 +104,33 @@ public class DHSessionKeyBuilder {
/**
* Construct a new DH key builder
*
* or pulls a prebuilt one from the queue.
*/
public DHSessionKeyBuilder() {
this(false);
DHSessionKeyBuilder builder = null;
synchronized (_builders) {
if (!_builders.isEmpty()) {
builder = (DHSessionKeyBuilder) _builders.remove(0);
if (_log.shouldLog(Log.DEBUG)) _log.debug("Removing a builder. # left = " + _builders.size());
} else {
if (_log.shouldLog(Log.WARN)) _log.warn("NO MORE BUILDERS! creating one now");
}
}
_context.statManager().addRateData("crypto.DHUsed", 1, 0);
DHSessionKeyBuilder builder = _builders.poll();
if (builder != null) {
if (_log.shouldLog(Log.DEBUG)) _log.debug("Removing a builder. # left = " + _builders.size());
_myPrivateValue = builder._myPrivateValue;
_myPublicValue = builder._myPublicValue;
_peerValue = builder._peerValue;
_sessionKey = builder._sessionKey;
// these two are still null after precalc
//_peerValue = builder._peerValue;
//_sessionKey = builder._sessionKey;
_extraExchangedBytes = builder._extraExchangedBytes;
} else {
_myPrivateValue = null;
_myPublicValue = null;
_peerValue = null;
_sessionKey = null;
if (_log.shouldLog(Log.INFO)) _log.info("No more builders, creating one now");
_context.statManager().addRateData("crypto.DHEmpty", 1, 0);
// sets _myPrivateValue as a side effect
_myPublicValue = generateMyValue();
_extraExchangedBytes = new ByteArray();
}
}
public DHSessionKeyBuilder(boolean usePool) {
_myPrivateValue = null;
_myPublicValue = null;
_peerValue = null;
_sessionKey = null;
/**
* Only for internal use
* @parameter usePool unused, just to make it different from other constructor
*/
private DHSessionKeyBuilder(boolean usePool) {
_extraExchangedBytes = new ByteArray();
}
@@ -189,18 +196,12 @@ public class DHSessionKeyBuilder {
}
private static final int getSize() {
synchronized (_builders) {
return _builders.size();
}
}
private static final int addBuilder(DHSessionKeyBuilder builder) {
int sz = 0;
synchronized (_builders) {
_builders.add(builder);
sz = _builders.size();
}
return sz;
/** @return true if successful, false if full */
private static final boolean addBuilder(DHSessionKeyBuilder builder) {
return _builders.offer(builder);
}
/**
@@ -210,7 +211,7 @@ public class DHSessionKeyBuilder {
*/
public BigInteger generateMyValue() {
long start = System.currentTimeMillis();
_myPrivateValue = new NativeBigInteger(KeyGenerator.PUBKEY_EXPONENT_SIZE, RandomSource.getInstance());
_myPrivateValue = new NativeBigInteger(KeyGenerator.PUBKEY_EXPONENT_SIZE, _context.random());
BigInteger myValue = CryptoConstants.elgg.modPow(_myPrivateValue, CryptoConstants.elgp);
long end = System.currentTimeMillis();
long diff = end - start;
@@ -314,6 +315,7 @@ public class DHSessionKeyBuilder {
* If there aren't enough bytes (with all of them being consumed by the 32 byte key),
* the SHA256 of the key itself is used.
*
* @return non-null (but rv.getData() may be null)
*/
public ByteArray getExtraBytes() {
return _extraExchangedBytes;
@@ -406,6 +408,7 @@ public class DHSessionKeyBuilder {
}
*/
/******
public static void main(String args[]) {
//if (true) { testValidation(); return; }
@@ -419,7 +422,7 @@ public class DHSessionKeyBuilder {
long negTime = 0;
try {
for (int i = 0; i < 5; i++) {
long startNeg = Clock.getInstance().now();
long startNeg = System.currentTimeMillis();
DHSessionKeyBuilder builder1 = new DHSessionKeyBuilder();
DHSessionKeyBuilder builder2 = new DHSessionKeyBuilder();
BigInteger pub1 = builder1.getMyPublicValue();
@@ -428,7 +431,7 @@ public class DHSessionKeyBuilder {
builder1.setPeerPublicValue(pub2);
SessionKey key1 = builder1.getSessionKey();
SessionKey key2 = builder2.getSessionKey();
long endNeg = Clock.getInstance().now();
long endNeg = System.currentTimeMillis();
negTime += endNeg - startNeg;
if (!key1.equals(key2))
@@ -458,10 +461,11 @@ public class DHSessionKeyBuilder {
} catch (InterruptedException ie) { // nop
}
}
******/
private static class DHSessionKeyBuilderPrecalcRunner implements Runnable {
private int _minSize;
private int _maxSize;
private final int _minSize;
private final int _maxSize;
private DHSessionKeyBuilderPrecalcRunner(int minSize, int maxSize) {
_minSize = minSize;
@@ -472,22 +476,28 @@ public class DHSessionKeyBuilder {
while (true) {
int curSize = 0;
long start = Clock.getInstance().now();
long start = System.currentTimeMillis();
int startSize = getSize();
// Adjust delay
if (startSize <= (_minSize * 2 / 3) && _checkDelay > 1000)
_checkDelay -= 1000;
else if (startSize > (_minSize * 3 / 2) && _checkDelay < 60*1000)
_checkDelay += 1000;
curSize = startSize;
while (curSize < _minSize) {
while (curSize < _maxSize) {
if (curSize < _minSize) {
for (int i = curSize; i < _maxSize; i++) {
long curStart = System.currentTimeMillis();
curSize = addBuilder(precalc(curSize));
if (!addBuilder(precalc()))
break;
long curCalc = System.currentTimeMillis() - curStart;
// for some relief...
try {
Thread.sleep(CALC_DELAY + curCalc * 10);
Thread.sleep(CALC_DELAY + (curCalc * 3));
} catch (InterruptedException ie) { // nop
}
}
}
long end = Clock.getInstance().now();
long end = System.currentTimeMillis();
int numCalc = curSize - startSize;
if (numCalc > 0) {
if (_log.shouldLog(Log.DEBUG))
@@ -496,16 +506,15 @@ public class DHSessionKeyBuilder {
+ (CALC_DELAY * numCalc) + "ms relief). now sleeping");
}
try {
Thread.sleep(30 * 1000);
Thread.sleep(_checkDelay);
} catch (InterruptedException ie) { // nop
}
}
}
private DHSessionKeyBuilder precalc(int i) {
private static DHSessionKeyBuilder precalc() {
DHSessionKeyBuilder builder = new DHSessionKeyBuilder(false);
builder.getMyPublicValue();
//_log.debug("Precalc " + i + " complete");
return builder;
}
}

View File

@@ -38,12 +38,13 @@ import net.i2p.data.Hash;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey;
import net.i2p.data.SimpleDataStructure;
import net.i2p.util.Log;
import net.i2p.util.NativeBigInteger;
/**
* Params and rv's changed from Hash to SHA1Hash for version 0.8.1
* There shouldn't be any external users of those variants.
* Hash variants of sign() and verifySignature() restored in 0.8.3, required by Syndie.
*/
public class DSAEngine {
private Log _log;
@@ -68,6 +69,22 @@ public class DSAEngine {
/** @param hash SHA-1 hash, NOT a SHA-256 hash */
public boolean verifySignature(Signature signature, SHA1Hash hash, SigningPublicKey verifyingKey) {
return verifySig(signature, hash, verifyingKey);
}
/**
* Used by Syndie.
* @since 0.8.3 (restored, was removed in 0.8.1 and 0.8.2)
*/
public boolean verifySignature(Signature signature, Hash hash, SigningPublicKey verifyingKey) {
return verifySig(signature, hash, verifyingKey);
}
/**
* @param hash either a Hash or a SHA1Hash
* @since 0.8.3
*/
private boolean verifySig(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey) {
long start = _context.clock().now();
try {
@@ -129,6 +146,22 @@ public class DSAEngine {
/** @param hash SHA-1 hash, NOT a SHA-256 hash */
public Signature sign(SHA1Hash hash, SigningPrivateKey signingKey) {
return signIt(hash, signingKey);
}
/**
* Used by Syndie.
* @since 0.8.3 (restored, was removed in 0.8.1 and 0.8.2)
*/
public Signature sign(Hash hash, SigningPrivateKey signingKey) {
return signIt(hash, signingKey);
}
/**
* @param hash either a Hash or a SHA1Hash
* @since 0.8.3
*/
private Signature signIt(SimpleDataStructure hash, SigningPrivateKey signingKey) {
if ((signingKey == null) || (hash == null)) return null;
long start = _context.clock().now();

Some files were not shown because too many files have changed in this diff Show More