Compare commits

...

1019 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
zzz
f02a0d96dd fix initialNews files in wrong place in installer 2010-12-21 22:05:33 +00:00
zzz
eefa732815 fix reseed fallback to http 2010-12-21 22:05:08 +00:00
zzz
299c1bd67b 0.8.2 2010-12-21 21:22:00 +00:00
zzz
1f22ae6a0c tweaks after review 2010-12-21 21:16:13 +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
a3644ccaa9 pluck of 43243e8d732573e9609515178f9a30080395334c 2010-12-19 15:48:29 +00:00
zzz
5e7bad2af0 explicit merge of 'e340ab5e817eb0ed7bb8058e3677aaea268d180a'
and '2c3eb1b692122c7c96b2c547532274f1068fc7f5'
2010-12-19 15:44:40 +00:00
zzz
de112fd63c explicit merge of 'daa35ac8b482063c4db4b6205ca5dacc045080a4'
and 'cde8ce662bee407206b7fea94beaa230f052f501'
2010-12-19 15:43:33 +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
m1xxy
c3f43bc63b add leading space   before … k 2010-12-19 03:55:57 +00:00
m1xxy
f1fe29e4ba add Portuguese translation of i2psnark 2010-12-19 03:52:06 +00:00
m1xxy
086004879d translation update i2psnark es 2010-12-19 03:51:23 +00:00
m1xxy
8ded0392bf translation changes de 2010-12-19 03:40:42 +00:00
m1xxy
58cacd88e4 proxy error translation changes de 2010-12-19 03:33:54 +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
zzz
360d96d085 de-thinsp until we can check UA for opera 2010-12-19 00:04:55 +00:00
sponge
f8ed3c561e Add original URI.java source 2010-12-18 19:58:29 +00:00
sponge
da8661526f Fix missing </A> 2010-12-18 19:57:56 +00:00
z3d
0d20d95ccd merge of '8ea404af31d0c1c0c9355425f6c880df4e763cea'
and '8edfe96d16e0a77f05f6370cc3e6436c6745303f'
2010-12-18 13:55:30 +00:00
z3d
5781880707 Classic & Midnight proxy error tweaks; favicon_light.ico (awaiting logic!). 2010-12-18 13:24:54 +00:00
zzz
59e5ec7426 fix 1 sec tag causing po error 2010-12-18 13:22:47 +00:00
zzz
7944065e3f cleanups and URL fixes 2010-12-18 13:22:07 +00:00
z3d
d3498138ac Classic filagree. 2010-12-18 07:35:31 +00:00
z3d
2302545a03 Classic futzage. 2010-12-18 07:24:08 +00:00
z3d
5531b4be51 Midnight & Dark mumblings. 2010-12-18 07:13:18 +00:00
z3d
3b4007f8fe Dark disturbance. 2010-12-18 07:02:49 +00:00
z3d
5a567705ca Midnight mod. 2010-12-18 06:51:23 +00:00
z3d
0a5818e1c3 Midnight tweak. 2010-12-18 06:28:21 +00:00
z3d
6c6609c937 Midnight manouevres. 2010-12-18 06:21:46 +00:00
z3d
7e3c347ac3 merge of '094945b98d69169e985ac8068256fec4ee5515f0'
and 'abb387ef4b4418e0e202272f5535a9f076f9da1d'
2010-12-18 05:20:48 +00:00
z3d
c09664c57a Dark 404 fixup. 2010-12-18 04:00:03 +00:00
z3d
73f5eed45c Light tweaks. 2010-12-18 02:30:25 +00:00
z3d
112f3736fb Readme (eng) space insertion. 2010-12-17 23:38:14 +00:00
z3d
c55778ea1a Dark polish. 2010-12-17 22:57: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
z3d
8a1fab0c2f merge of 'a5db72a1d84bd8d00d11acfbd2cd21ad6281e8ef'
and 'cd559af7f771ba5ff6933d3b1315f2836b3fe411'
2010-12-17 21:43:20 +00:00
z3d
65c623a9cc Mods to light, dark & midnight console themes (mostly news tweaks). 2010-12-17 21:43:08 +00:00
duck
4e4165e30d Update Dutch translations 2010-12-17 16:12:13 +00:00
hiddenz
ef340e6b3e merge of '83219c8a9d6734e695b300d9eefc8786b82671a1'
and 'c5b24b88c7bba734c5412f4dd03d8dce069c5ba9'
2010-12-16 15:58:32 +00:00
hiddenz
cab63efacf routerconsole: update russian translation 2010-12-16 15:56:30 +00:00
mathiasdm
6bab0e7251 Added https support for r31453.ovh.net 2010-12-16 07:19:07 +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
hiddenz
cb7e6cfb38 i2ptunnel: update russian translation 2010-12-15 19:42:28 +00:00
hiddenz
aca0ae2103 i2psnark: update russian translation 2010-12-15 19:42:10 +00:00
hiddenz
ed9b0bbdd5 routerconsole help_ru.jsp: small fix 2010-12-15 18:46:58 +00:00
hiddenz
97bb51c67b dnf-header_ru.ht: fix typo 2010-12-15 17:20:43 +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
mathiasdm
a85f931c1c Fixed r31453.ovh.net reseed url (small change).
SSL still needs to be added for this url.
2010-12-15 16:54:36 +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
46b8befda5 drop non-country flags 2010-12-14 15:33:27 +00:00
zzz
2082feeaa9 one more log error to a warn (ticket #356) 2010-12-14 15:14:36 +00:00
zzz
f9c2624b24 disable log priority override for now 2010-12-14 14:51:23 +00:00
zzz
8bcfdc3c6e i2ptunnel ui fixes 2010-12-14 14:50:52 +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
z3d
1a41334e34 Dark & Classic tweaks. 2010-12-14 07:10:58 +00:00
z3d
311f295f22 I2PTunnelManager "Midnight" polish. 2010-12-14 06:31:00 +00:00
z3d
194abc7916 Readme (eng): no leading space before %hellip; 2010-12-13 19:39:06 +00:00
z3d
30145ff298 License typo fix. 2010-12-13 19:19:59 +00:00
z3d
f8bf32e05c Update license. 2010-12-13 19:19:04 +00:00
z3d
35feab3dad Classic tweaks. 2010-12-13 19:15:47 +00:00
z3d
7f3650650d Classic tweakery. 2010-12-13 17:48:07 +00:00
z3d
57edfbbc15 Classic massage. 2010-12-13 16:48:11 +00:00
z3d
7e1a5d5cb5 Light touch. 2010-12-13 15:42:51 +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
m1xxy
af8751a3a4 new translation update for de and es 2010-12-13 00:26:26 +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
7c63866c51 * i2psnark:
- Fix end-game deadlock
      - Fix last-modified check for multifile torrents, causing
        apparent loss of data after abnormal exit
      - UI Tweaks
2010-12-12 14:49:30 +00:00
z3d
d4b0bfda7e merge of '4be12c91831cc6b24ef6fcf16af9cbb9fa32069d'
and 'c578a1847c62244cfc8308021014c94afef01606'
2010-12-11 18:06:01 +00:00
z3d
c3597cfd99 Readme (eng) typo fix. 2010-12-11 16:43:06 +00:00
z3d
5f91be1b47 -36rc. 2010-12-11 14:49:28 +00:00
z3d
50caf108cc Midnight twickery. 2010-12-11 14:36:16 +00:00
z3d
dea69fee76 Midnight tweaks. 2010-12-11 14:35:27 +00:00
zzz
0be2ca8beb * I2CP: Change a log error to a warning (ticket #353) 2010-12-11 14:24:27 +00:00
z3d
eec96ff670 Midnight logo tweaks. 2010-12-11 14:12:28 +00:00
z3d
8c4298167b Midnight header logo refresh. 2010-12-11 14:06:07 +00:00
zzz
2ca8fc6e62 * i2psnark:
- Restore text (ticket #273)
      - Fix several HTML errors (ticket #273)
      - Fix HTML error causing info links to be unclickable in dillo (tiicket #273)
      - Fix alt text duplicated or looking bad in text browsers (ticket #273)
      - Fix Opera button errors (ticket #332)
      - Fix POST resubmission errors (ticket #334)
      - Catch FetchAndAdd copy error (ticket #352)
      - Set permissions on downloaded torrent files
      - Hide some columns when not running
      - Lots of spacing cleanups
      - Rename images so users don't end up with unused files
      - Remove ~15 unused images
      - Clean up theme selection speed-coding exercise
      - Indent fixes
2010-12-11 13:57:14 +00:00
zzz
89b3e3bcb4 * TunnelPoolManager: Fix rare startup NPE (http://forum.i2p/viewtopic.php?t=5192) 2010-12-11 13:31:23 +00:00
zzz
b55b552e06 * Plugins: Better handling of signing keys (Ticket #351) 2010-12-11 13:30:34 +00:00
zzz
3098d6ef8e * News: XML fixes (ticket #350) 2010-12-11 13:28:16 +00:00
z3d
036e36f611 Light tweak. 2010-12-11 13:28:13 +00:00
z3d
11de315834 Dark tweak. 2010-12-11 13:27:51 +00:00
zzz
638e04beb8 * Log: Don't double-timestamp CRITS in wrapper.log 2010-12-11 13:25:58 +00:00
zzz
10f674a782 * Build: Fix 'ant distclean poupdate' again 2010-12-11 13:24:26 +00:00
zzz
8d54dbac9a merge of 'ba7a210d3d3729205c9f020868e4830f34d74e19'
and 'baae7f79d6af8cd227c59257a3a5ec11c4179c3d'
2010-12-11 13:12:07 +00:00
z3d
198280eea5 Midnight under the moon. 2010-12-11 13:09:12 +00:00
z3d
6644bb0f53 Midnight perspectives. 2010-12-11 13:08:41 +00:00
z3d
99ebcb5e17 Classic doublebyte glyph polish. 2010-12-11 06:12:56 +00:00
z3d
624aff645d Classic changes, sotto voce. 2010-12-11 05:58:41 +00:00
z3d
b0ac5d3bdd Classic smoothness. 2010-12-11 05:21:21 +00:00
z3d
3887b0c4e4 Readme (eng): more clarifications. 2010-12-11 04:42:30 +00:00
z3d
1abf447f85 Dark twiddle. 2010-12-11 03:38:55 +00:00
z3d
587b7861cd Light touch. 2010-12-11 03:38:28 +00:00
z3d
4833b68fc0 Midnight top 'n tail. 2010-12-11 03:34:38 +00:00
z3d
a292770415 Classic enhancements. 2010-12-11 03:21:46 +00:00
z3d
b77bcd4692 Readme (eng) finessing. 2010-12-11 03:21:04 +00:00
z3d
ec9238c99c Readme (eng): make or <br> time (removals division). 2010-12-11 02:49:56 +00:00
z3d
a9f1f1bc1f Readme (eng) detailing. 2010-12-10 20:56:45 +00:00
z3d
ceb45dd17b Classic polish. 2010-12-10 20:49:30 +00:00
z3d
b0564a8aeb Classic ie shimming. 2010-12-10 20:48:09 +00:00
z3d
b7d89a9796 Classic load balancing. 2010-12-10 20:34:38 +00:00
z3d
49a03bdde9 More classic finessing. 2010-12-10 20:31:44 +00:00
z3d
173e03a050 Classic ieshim tweaks. 2010-12-10 20:24:12 +00:00
z3d
651e258de0 Classic <code> tweaks. 2010-12-10 20:17:39 +00:00
z3d
4e7b013ce6 Classic css tweakery. 2010-12-10 20:09:46 +00:00
z3d
60b60f20c9 Classic polish. 2010-12-10 20:09:15 +00:00
z3d
f196ec8854 Classic gloss. 2010-12-10 18:19:07 +00:00
z3d
507dc44b1d Classic ieshimmery. 2010-12-10 18:18:37 +00:00
z3d
36305db762 Readme (eng): minor futzage. 2010-12-10 14:57:35 +00:00
z3d
ea3f886597 Readme (eng): typo fixes and clarfications. 2010-12-10 11:13:27 +00:00
mathiasdm
6983380668 Fixed up security fix, so it filters correctly for clients and servers. 2010-12-10 06:04:23 +00:00
z3d
59343b5899 Readme (eng): s/severs/servers 2010-12-09 16:40:37 +00:00
z3d
6df27b273d Vanilla/Ubergine tweaks. 2010-12-08 06:46:42 +00:00
z3d
1a3076a162 Dark updates. 2010-12-08 06:24:26 +00:00
z3d
e46d5c6658 Dark news reversion to radar. 2010-12-08 06:23:19 +00:00
z3d
0fdb10940e -35rc. 2010-12-08 06:00:04 +00:00
z3d
29b8788fc2 Readme (eng): typo fixes. 2010-12-08 05:47:01 +00:00
z3d
6996c60a41 I2PSnark: vanilla/ubergine status line tweaks. 2010-12-08 05:34:22 +00:00
z3d
7d5cfecb64 I2PSnark: Status spacing tweaks. 2010-12-08 05:29:04 +00:00
z3d
6fe4477ccb I2PSnark: Don't forget our priority tooltip! 2010-12-08 04:43:55 +00:00
z3d
e349e13efe I2PSnark: Status updates! 2010-12-08 03:47:36 +00:00
z3d
020da9d0be I2PSnark: Priority tweaks. 2010-12-08 03:24:25 +00:00
z3d
022e77d58d merge of '271d5fa6e5479cee64f70863f31de61f79fa2e03'
and '79a880c604fbbd9dfc56596d8d9c9009b233ca9d'
2010-12-08 03:09:28 +00:00
z3d
7280110c7b I2PSnark: Long awaited changes to file and size header icons. 2010-12-08 03:00:23 +00:00
mathiasdm
03ff26acc7 Hide HTTP server name (replace by I2PServer) to avoid server detection
(flaw successfully tested by Adrian Crenshaw -- thanks!).
2010-12-07 21:38:13 +00:00
z3d
26356ce35f -34rc. 2010-12-07 18:53:12 +00:00
z3d
1ddf19c7f9 I2PSnark: follow through with vanilla header images. 2010-12-07 18:51:29 +00:00
z3d
f9e05f5e56 I2PSnark: Add bittorrent logos to head_torrent.png. 2010-12-07 18:24:35 +00:00
z3d
001e5a0816 I2PSnark: Footer icon spacing adjustment. 2010-12-07 18:07:42 +00:00
z3d
7e00d830a9 I2PSnark: header graphic tweaks. 2010-12-07 17:51:14 +00:00
z3d
c1f992f21c I2PSnark: Lose the motorcycles! 2010-12-07 17:06:47 +00:00
z3d
510b4e295b Light tweaks. 2010-12-07 14:03:39 +00:00
z3d
eeb7669c2e Light tweaks. 2010-12-07 00:23:57 +00:00
z3d
2486ebbbd1 Ubergine screenlog tweaks. 2010-12-07 00:04:27 +00:00
z3d
a1698b8eab Light, ubergine & snark changes. 2010-12-06 17:51:10 +00:00
z3d
274272111f Light finessing. 2010-12-06 15:40:57 +00:00
z3d
a723bce18a Light blue adjustment. 2010-12-06 15:20:25 +00:00
z3d
5a0fcc7791 -33rc. 2010-12-06 14:03:03 +00:00
z3d
b4d2eda02c Ubergine lovefest. 2010-12-06 13:54:06 +00:00
z3d
6360fba8f8 Vanilla refinement. 2010-12-06 13:45:14 +00:00
z3d
e7426f727e Vanilla essence. 2010-12-06 13:27:02 +00:00
z3d
51ba6c16fc I2PSnark resolutions. 2010-12-06 13:15:43 +00:00
m1xxy
6749931450 de translation update for 0.8.2 2010-12-06 10:43:05 +00:00
z3d
43e09b00b6 I2PSnark: More overflow fixes. 2010-12-06 04:06:20 +00:00
z3d
bd11011d01 I2PSnark: downloading subsisnark arrows. 2010-12-06 02:34:48 +00:00
z3d
a31e3a2a1f Ubergine tweaks. 2010-12-06 02:01:38 +00:00
z3d
6ae3d8ed01 Snark tweak. 2010-12-06 00:40:58 +00:00
z3d
e6c4d23402 Snark refinements. 2010-12-06 00:35:03 +00:00
z3d
f054663b17 -32rc 2010-12-05 23:50:12 +00:00
z3d
78b990880c I2PSnark: Wrap fixes. 2010-12-05 23:36:25 +00:00
z3d
6a11c472ed I2PSnark: seeding.png tweak. 2010-12-05 21:11:36 +00:00
z3d
c8d9dee46e Dark enhancer. 2010-12-05 20:17:07 +00:00
z3d
e4417c3582 ScarfAce tweak. 2010-12-05 20:05:18 +00:00
z3d
55d1bf353d Tweaks. 2010-12-05 19:44:03 +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
z3d
3d0394e63b Readme tweaks. 2010-12-05 16:25:41 +00:00
z3d
a00845ce4a ScarfAce refreshes. 2010-12-05 14:35:30 +00:00
z3d
57963c9c10 Readme (eng): more futzage! 2010-12-05 13:14:43 +00:00
z3d
c13d2c2dfc Readme: add missing futz (absence spotted by Mathiasdm). 2010-12-05 12:55:10 +00:00
z3d
26fda3944b Readme (eng): futzinger (noun). an zealous partaker of futzing. 2010-12-05 12:24:29 +00:00
z3d
bbad4dd5fa Readme tweaks. 2010-12-05 05:57:15 +00:00
z3d
b411de7bf8 Light tweaks. 2010-12-05 05:51:25 +00:00
z3d
9664ac2a8b Classic&Midnight link.png refresh. 2010-12-05 05:09:44 +00:00
z3d
0bab0ae217 merge of '354d421d8e1f234007967cec4461aedb532ae89e'
and '56635df32be529c80a40a3d84e01ef858c7346ec'
2010-12-05 04:32:28 +00:00
z3d
b5be73a15f Dark tweaks. 2010-12-05 04:31:33 +00:00
z3d
1531fde198 Muffing about with dark iconography. 2010-12-05 04:07:20 +00:00
zzz
c94fa6ef17 tweaks 2010-12-05 04:05:20 +00:00
zzz
3872cad2fb * DataHelper: Have readLong() and readString() throw an
EOFException instead of a DataFormatException on EOF,
      which should lower the log severity in I2CP and I2NP
      when a client or peer disconnects.
2010-12-05 04:05:10 +00:00
z3d
9c9d91c5d3 ScarfAce vectorizations. 2010-12-05 04:03:59 +00:00
z3d
44d5dd65ba Light tweaks. 2010-12-05 03:18:03 +00:00
z3d
e577379519 Mostly theme graphics cruft removal. 2010-12-05 02:43:37 +00:00
z3d
5b0a9fd287 Readme (eng): more clarficatory amendments. 2010-12-05 02:35:03 +00:00
z3d
aa7e1cf72f Dark rumblings. 2010-12-05 02:05:26 +00:00
z3d
bf9ce6e82e Readme (eng): adjustment. 2010-12-05 01:20:27 +00:00
z3d
2403d82a7b ScarfAce muscles in on the dark news. 2010-12-05 01:02:43 +00:00
z3d
225cd17cf5 Readme (eng): more finessing. 2010-12-05 00:42:29 +00:00
z3d
6efec491c6 Readme (eng): more elucidcation. 2010-12-05 00:28:58 +00:00
z3d
589f4ba29d Readme (eng): clarifications, qualifications & enhancements. 2010-12-04 23:53:20 +00:00
z3d
11f0259b36 Readme (eng): more finessing and clarificationary tweaks. 2010-12-04 23:43:10 +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
z3d
3d5a42658f Readme (eng): clarification(s). 2010-12-04 17:24:20 +00:00
z3d
8f104223df Dark news. 2010-12-04 17:09:26 +00:00
z3d
c713ff6ac0 ScarfAce goes underground. 2010-12-04 16:59:21 +00:00
z3d
2b11267b45 Light webskit/shopera fixes. 2010-12-04 16:46:42 +00:00
z3d
9fbeca08e1 -30 2010-12-04 16:40:12 +00:00
z3d
b23abfb8fc Light enhance. 2010-12-04 16:37:41 +00:00
z3d
e88a1d2a4d Scarface bling. 2010-12-04 16:30:40 +00:00
z3d
62be1bf1ce Readme (eng): Troubleshoot kickbacks. 2010-12-04 15:39:43 +00:00
z3d
ab29e1e560 Readme troubleshooting massage. 2010-12-04 14:50:22 +00:00
z3d
176f54023a Readme (eng) edits. 2010-12-04 14:40:08 +00:00
z3d
c36d2409a7 Dark tweaks. 2010-12-04 14:13:53 +00:00
z3d
333e015a53 merge of '0053ae5e6e0a984e8e8876549da6851de16970d5'
and '23394c79d24fe3cfcdf8b59caf2a707175a60e4f'
2010-12-04 14:10:22 +00:00
z3d
d0ac53fa5e ScarfAce downsizing. 2010-12-04 14:08:59 +00:00
z3d
d2a1a6d113 ScarfAce puts his stash away. 2010-12-04 13:53:56 +00:00
m1xxy
d236a3c72c readme typos and order 2010-12-04 13:04:21 +00:00
z3d
5474646fb2 Readme (eng): enhance troubleshooting section. 2010-12-04 04:50:00 +00:00
z3d
8b75b3c773 Dark stirrings. 2010-12-04 03:35:43 +00:00
z3d
36a7fa1b64 Dark nuance. 2010-12-04 03:28:19 +00:00
z3d
46dcba12ed Dark polish. 2010-12-04 03:16:40 +00:00
z3d
6d3b09a7a2 -29. (ScarfAce Special Edition). 2010-12-04 02:59:02 +00:00
z3d
e9aca5dacb Dark undertones. 2010-12-04 02:55:51 +00:00
zzz
467b082e82 * I2PTunnel:
- Limit server blockingHandle threads
      - Run standard server blockingHandles inline
2010-12-04 02:03:08 +00:00
z3d
6b8f420ad0 -28 2010-12-04 01:54:37 +00:00
z3d
42753be69b Light embellishments. 2010-12-04 01:41:54 +00:00
z3d
1054080cf2 merge of '2dfae8b7197d2abdca4c46244533b97fede046c0'
and '3742a97ed79b29cb38f0ef3919dcf036c126efe2'
2010-12-04 00:49:17 +00:00
z3d
a6946803e4 Light adjustment, please remain seated. Refreshments will be served shortly. 2010-12-04 00:48:02 +00:00
z3d
3f3c44d432 More Light meddling. 2010-12-03 23:09:19 +00:00
z3d
f23b1880f5 Light shift. 2010-12-03 22:43:27 +00:00
z3d
1330930867 Dark rumblings. 2010-12-03 22:24:45 +00:00
z3d
5c3e5cf1e6 Dark dealings. 2010-12-03 22:16:53 +00:00
z3d
d60da1bf63 Light&Dark Opera/Webkit enhancements. 2010-12-03 22:03:41 +00:00
m1xxy
26d423ff6b readme_es s/P/p 2010-12-03 21:33:54 +00:00
zzz
5ab813179d dont update stats after failure 2010-12-03 21:30:32 +00:00
z3d
92254f4295 Light psychoacoustic adjustments. 2010-12-03 21:17:08 +00:00
z3d
e59797e660 Light spatial reordering. 2010-12-03 21:08:02 +00:00
z3d
c7f6e72807 Light frolics in the snow (reported by postman). 2010-12-03 20:52:54 +00:00
zzz
8976746867 mindless history.txt servlet 2010-12-03 20:40:34 +00:00
z3d
f4ceb163bd host.txt: add planet.i2p; more light tweakage. 2010-12-03 19:24:59 +00:00
z3d
e3f2673919 Light touches. 2010-12-03 19:17:22 +00:00
z3d
4a1235a03f proxy error tweaks. 2010-12-03 18:04:29 +00:00
z3d
33dde2b44e -27 2010-12-03 17:28:44 +00:00
z3d
3f63633b45 Light spruce. 2010-12-03 17:27:39 +00:00
zzz
fabbda659b I2CP internal mode tweaks 2010-12-03 17:23:36 +00:00
z3d
2b87eb86ef Light embellishment. 2010-12-03 17:12:54 +00:00
zzz
e9e1890b14 * I2PTunnel:
- Extend header timeouts for HTTP and IRC server tunnels
2010-12-03 17:01:51 +00:00
z3d
61f6ac56e0 -26 2010-12-03 16:54:47 +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
z3d
cfc69c22b5 Light hors d'oeuvres, served on a bed of caramelized pig liver (snaffled by postman). 2010-12-03 16:42:39 +00:00
z3d
a20ed8aa18 Light logo, salad on the side (spotted by postman). 2010-12-03 16:24:05 +00:00
z3d
b4fce55aee Readme (eng): typo police. 2010-12-03 15:29:25 +00:00
z3d
19fb2877d3 -25 2010-12-03 15:24:38 +00:00
z3d
9906fc4bdf Light console_big.css finesse. In memory of Bruce Lee. 2010-12-03 15:22:35 +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
z3d
94620d6acb Light logo phasers set to stun. 2010-12-03 15:11:59 +00:00
z3d
1442fd68f3 light/console_big.css added to the workspace manifest. 2010-12-03 15:06:41 +00:00
z3d
90e87046aa Light logo adulteration. 2010-12-03 14:47:31 +00:00
z3d
f088302b05 More light spiff, extra yoghurt (spotted by postman). 2010-12-03 14:15:54 +00:00
z3d
24839d9b04 -24 ftw! 2010-12-03 13:58:37 +00:00
z3d
ef028005bf Light spiff. 2010-12-03 13:56:22 +00:00
z3d
240642803a Light finesse. 2010-12-03 13:24:27 +00:00
z3d
efd11d1950 Light sleight. 2010-12-03 12:22:39 +00:00
z3d
2f49575adb Light table magic. 2010-12-03 11:53:57 +00:00
z3d
e7dc90907d light magic table tweakery. 2010-12-03 07:17:27 +00:00
z3d
56fbb54580 trip the light fantastic. 2010-12-03 07:15:06 +00:00
z3d
cf236deec0 Light adjustment. 2010-12-03 07:03:32 +00:00
z3d
594765dd4e Light futz. 2010-12-03 06:54:30 +00:00
z3d
17526f435c -23 2010-12-03 06:50:56 +00:00
z3d
b649d8424a Light magic touch. 2010-12-03 06:09:11 +00:00
z3d
faf3d08164 proxy error logo refresh. 2010-12-03 05:42:47 +00:00
z3d
e4281cfbab classic ieshim tweaks. 2010-12-03 02:56:15 +00:00
z3d
1b36b3efe1 Light manoeuvring. 2010-12-03 02:35:24 +00:00
z3d
336f576499 merge of 'c824ff0c12a4b616407365fc175b161e7c3736df'
and 'dede80d3699065f495e330c8bb8e9e579882757c'
2010-12-02 18:44:35 +00:00
z3d
3e0da23b4d Readme (eng) futz. 2010-12-02 18:43:25 +00:00
zzz
acf09bb3d0 merge of '1cf0e4a5d377da8d3a8a8bd80a184c589fab1238'
and 'd95ca1deac504336bf9a646b4a6753b35ca6b40b'
2010-12-02 18:31:09 +00:00
zzz
5ba101063a * I2NP: Allow message to be written more than once,
instead of throwing an IllegalStateException
2010-12-02 18:12:38 +00:00
zzz
8f8fb0e5cb log tweak 2010-12-02 18:11:30 +00:00
z3d
c1e56cd05c hosts.txt: add i2plugins.i2p & i2pbote.i2p 2010-12-02 18:01:03 +00:00
zzz
2126b5156e format refresh time 2010-12-02 16:18:09 +00:00
zzz
3d6a5bd9e7 fix extension messages 2010-12-02 16:17:28 +00:00
zzz
2c8421d8ad * Transport: Hamachi address block 5/8 assigned by IANA 2010-12-02 13:01:25 +00:00
zzz
d226d6047f javadoc 2010-12-02 12:58:53 +00:00
zzz
9a6a66d70f * Streaming: Restore I2PSocketManagerFull as public
(broke jwebcahe ticket #345)
2010-12-02 12:58:40 +00:00
z3d
3c51725916 Readme (eng): Attribute Complication as I2Phex maintainer, noting that I2Phex is looking for new devs. 2010-12-02 01:15:05 +00:00
z3d
6eee69835d Light tweak. 2010-12-01 21:32:14 +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
m1xxy
e3bb912d08 translation tweaks de & es 2010-12-01 18:17:26 +00:00
z3d
28ee1d1f1f I2PSnark: trackererror.png update. 2010-12-01 17:56:58 +00:00
z3d
5fa17238e0 Console: Midnight i2plogo refresh. 2010-12-01 16:33:35 +00:00
z3d
2f044f1345 Dark updates. 2010-12-01 15:58:46 +00:00
z3d
17afef63f2 I2PSnark: Ubergine subisnark love. 2010-12-01 15:40:53 +00:00
z3d
8d62632945 -19 2010-12-01 15:11:44 +00:00
z3d
35a72e8a97 merge of 'c4649554b77db6d5f9d4e4c7aaa8e6830c9f4937'
and 'ca22cd7740376a68a2a9b094458abb2b5dc897d5'
2010-12-01 15:09:17 +00:00
z3d
9f3bcc20f9 I2PSnark: Update subisnark images. Console: Midnight theme tweakage. 2010-12-01 15:01:22 +00:00
z3d
a2a406fb7c Console themes: rework ieshim.css for classic/ie; Classic & Light tweaks; I2PSnark vanilla/ubergine edits. 2010-12-01 13:10:24 +00:00
zzz
293eea9e38 try to fix log flush error at file rotation 2010-11-30 19:04:03 +00:00
m1xxy
6de6fb1b56 es tweaks by user 2010-11-30 18:26:04 +00:00
zzz
e04252f2e7 merge of '758ffc5607f3a32a8aeaa7dd5a1d1b839629d33d'
and 'c366ec63b4c58df5f6fd47dcf1bddd1eb48f43c8'
2010-11-30 15:56:39 +00:00
zzz
578d656f9d change port change message from error to info 2010-11-30 15:22:17 +00:00
zzz
c97e72d050 formatSize tweak 2010-11-30 15:15:39 +00:00
zzz
ad54822383 * i2psnark: Move PeerCheckerTask from Timer to SimpleTimer2 to save some threads 2010-11-30 15:12:18 +00:00
zzz
243bd412e1 * I2CP: Try to hide Pipe closed messages (several tickets) 2010-11-30 15:08:51 +00:00
zzz
45b8d8b6b5 * Logging:
- Limit buffer size; block and wakeup writer when full
      - Limit errors written to system log
      - Add method to force a log below the current level
2010-11-30 15:07:45 +00:00
m1xxy
f7ed341263 requested changes to de 2010-11-30 15:05:14 +00:00
zzz
9147fddb8e * Streaming: Change some log errors to warnings (tickets 76, 341 and others) 2010-11-30 15:04:18 +00:00
m1xxy
db23534e36 merge of '0e94b0f3b3818b53b029fcce7e9ca64680dd4391'
and '5d73bb2f881c3ef24f74af899f7451da1e5f42d4'
2010-11-30 11:17:54 +00:00
m1xxy
4efeecdaba minor de tweaks 2010-11-30 11:16:04 +00:00
z3d
59b53eb6f5 Console translation (de): s/Router-Einstellungen/Einstellungen (sidepanel). 2010-11-29 20:08:27 +00:00
z3d
2980794645 Console translation (fr): s/I2P Configuration Interne/Configuration (sidebar). 2010-11-29 19:55:18 +00:00
z3d
f12556714a -16 2010-11-29 18:18:38 +00:00
z3d
0f288ed720 Console: "light" theme refresh. 2010-11-29 18:16:49 +00:00
z3d
e243f90b35 Readme tweaks; Dark manoeuvres. 2010-11-29 17:00:26 +00:00
zzz
601abdce6d Lock down streaming classes not in the API. Holler if this breaks any external apps. 2010-11-29 15:39:55 +00:00
zzz
b5f652ef04 tweak 2010-11-29 15:36:05 +00:00
zzz
671f48e77e -14 2010-11-29 13:51:39 +00:00
zzz
174c222662 * UDP:
- Fix bug causing PacketPusher to loop quickly instead of sleeping
      - Fix udp.sendCycleTime and sendCycleTimeSlow stats
      - Fix speed values on peers.jsp
      - Try to fix rare NPE (ticket 298)
2010-11-29 13:15:11 +00:00
zzz
d31113255e * Logging:
- Use System locale and time zone for default date/time format,
        so it matches the wrapper log time (we can't set the wrapper log time zone).
        (existing installs must remove logger.dateFormat line
         in logger.config to get system default format)
      - Force RuntimeExceptions to CRIT level
      - Don't have log() count buffer size
2010-11-29 13:13:02 +00:00
zzz
a86fef2a21 * i2psnark: Don't timeout queued piece messages 2010-11-29 13:08:03 +00:00
z3d
2138599567 I2PSnark: Vanilla edits. 2010-11-29 05:36:54 +00:00
z3d
8d2ea460c8 I2PSnark: Vanilla finessing. 2010-11-29 04:51:27 +00:00
z3d
054eae8718 Readme tweak; dark tweaks. 2010-11-28 23:29:02 +00:00
z3d
c23116bca8 Readme: add planet.i2p to our list of I2P resources. 2010-11-28 23:23:46 +00:00
z3d
47ce7b24fa Console: Add console_big.css to "dark" theme to accomodate doublebyte glyphs better. 2010-11-28 22:58:07 +00:00
z3d
4a94d48ef7 More readme tweakage. 2010-11-28 20:41:26 +00:00
z3d
d2afaa4586 Readme tweaks 'n fiddles. 2010-11-28 20:36:05 +00:00
z3d
140d893364 Readme futzes. 2010-11-28 20:16:09 +00:00
z3d
693945a471 I2PSnark: s/Ignore/Skip 2010-11-28 17:53:43 +00:00
z3d
f3fc28ff74 Readme tweaks. 2010-11-28 13:29:28 +00:00
m1xxy
3480f8e827 tiny reformulation in fr (user) 2010-11-28 13:03:48 +00:00
m1xxy
de85a8d3f9 merge of 'ac50d73893f7b61e4c91b21080551261aaf0858d'
and 'cb91ed6dab8fa6b20f179c822df7402805e853a6'
2010-11-28 12:59:49 +00:00
m1xxy
77221de703 tiny reformulation in es/pt (user) 2010-11-28 12:59:30 +00:00
m1xxy
26d5390e85 merge of '8f40f2b7ad2272ecedca14c17598ecaf409340e8'
and 'da96c40b16f6e3f2e4e044f0f48cb53f1e9f2264'
2010-11-28 12:36:17 +00:00
m1xxy
1ddea5c134 fix initial news pt 2010-11-28 12:36:11 +00:00
z3d
48adefca22 merge of '5f806c16d9ddce033dc0527c22c5559e00f692e5'
and '893000f2731ec12111a70dbb912005b82642fcaa'
2010-11-28 12:05:14 +00:00
z3d
609a17f438 Light tweak. 2010-11-28 12:03:45 +00:00
z3d
e37f831ce6 Dark&Vanilla tweaks. 2010-11-28 11:40:07 +00:00
zzz
b9413d540a -13 2010-11-28 04:02:05 +00:00
zzz
a52fb65c64 * i2psnark:
- Fix NPE and other partials bugs
      - More extension message stubbing
      - Log tweaks
2010-11-28 04:01:20 +00:00
zzz
9ba86e86aa * I2PTunnel: Deprecate destFromName() 2010-11-28 04:00:02 +00:00
zzz
612d06bd53 * Build: Move all dependencies to top-level build.xml,
so each sub-build.xml is only executed once (true DAG)
2010-11-28 03:56:56 +00:00
z3d
a59e52bff5 Dark tweak. 2010-11-28 02:25:48 +00:00
z3d
5b5459f6e8 Readme edits. 2010-11-28 02:20:51 +00:00
z3d
86bbb8578d Classic tweak. 2010-11-28 02:01:24 +00:00
z3d
0e19f45862 More readme edits. 2010-11-28 01:56:11 +00:00
z3d
8f3d4e8e6b Readme edits. 2010-11-28 01:09:55 +00:00
z3d
bcf1999347 merge of '72b051da2fb0f5215c2c90ba63559876f8909937'
and 'd34a77db6375e8df16bb5fdf76aaa43ab630c704'
2010-11-28 00:58:16 +00:00
z3d
ab80fafa67 Readme tweaks and edits. 2010-11-28 00:54:33 +00:00
m1xxy
0d3f85a2c4 more br->pt conversions 2010-11-27 18:18:23 +00:00
z3d
6a9ea5a131 Snark control button tweak. 2010-11-27 17:58:38 +00:00
z3d
48419588c3 Vanilla tweaks. 2010-11-27 17:56:49 +00:00
z3d
8aaa2ebb3c History.txt typo fix. 2010-11-27 17:53:36 +00:00
z3d
0ea55cbcb8 History.txt 2010-11-27 17:13:24 +00:00
z3d
9158ce9ae2 merge of '0f2ea1b227d59edae92a0450663f0ac1418bd153'
and '846a3cf81acf27ff8da92e611833e5651af94496'
2010-11-27 17:11:36 +00:00
zzz
fdf2b5f7d2 -12 2010-11-27 16:36:46 +00:00
z3d
ce332a407e I2PSnark: tiles for vanilla theme. 2010-11-27 16:35:14 +00:00
zzz
8e98f58f6d merge of '2b0329ad66b84d90d1b7e6e1a6247c6d826321f9'
and '77a4e2e18ab0e48d6f102388838e1367c1d56ebd'
2010-11-27 16:34:15 +00:00
z3d
fdb19bb671 I2PSnark: Vanilla theme - theme specific control buttons. 2010-11-27 16:31:32 +00:00
z3d
b61f564d3b merge of '6c704c4130747ce7d75627bcdf68f1b5195fb0bb'
and '73917249645c8c29f9d46f7ed097290016161e15'
2010-11-27 15:00:08 +00:00
z3d
b805bc7a56 New snark theme: "vanilla". 2010-11-27 14:55:45 +00:00
zzz
3c45b038c6 * i2psnark:
- Drop queued outbound requests when choked
      - Redo some data structures and locking to hopefully prevent deadlock
      - Memory reduction part 3: Return partial pieces to PeerCoordinator when choked
2010-11-27 14:34:08 +00:00
sponge
8c5fd29233 Plugin: ticket 336 fix NPE 2010-11-27 13:52:57 +00:00
zzz
ff828e6417 * Build:
- Add man pages to package
      - New updaterWithJavadoc target
    * Console:
      - Add link to javadocs if installed
2010-11-27 13:50:33 +00:00
zzz
28b4239d08 linkify message 2010-11-27 13:48:53 +00:00
zzz
5b951b5b4b javadoc 2010-11-27 13:48:01 +00:00
zzz
df4f40f6f4 log cleanup 2010-11-27 13:46:33 +00:00
zzz
595b562461 prep for another config option 2010-11-27 13:45:09 +00:00
zzz
daa4ff6308 fix race NPE at stream close 2010-11-27 13:44:42 +00:00
zzz
2d0e8b6ec8 fix configstats NPE 2010-11-27 13:43:48 +00:00
z3d
f7c85a4746 merge of '83099cd337dd977a73da45025dd3e2fbff708cee'
and 'a69c4ee8775f64e852719b159c9fc5091405d8cf'
2010-11-27 11:59:02 +00:00
z3d
bcf27dbe12 I2PSnark: Echo themename in screenlog when changed (thanks to sponge); readme tweaks. 2010-11-27 11:53:06 +00:00
sponge
8eef3808a4 Slackware: bump i2p-base version, so that it can be upgraded with the new
base code fixes.
2010-11-27 11:17:19 +00:00
z3d
49a946d0f1 Readme (eng) futzing. 2010-11-27 04:54:47 +00:00
z3d
64999e7f01 Readme (eng): more futzing. 2010-11-27 04:23:20 +00:00
z3d
be7609baed Readme: s/anonymity network/invisible internet. 2010-11-27 04:14:10 +00:00
z3d
d57988fbbc Readme: s/darknet/anonymity network. 2010-11-27 04:07:27 +00:00
z3d
a034a8c4f5 Readme (eng) finessing. 2010-11-27 03:42:01 +00:00
z3d
cb99f4191f Readme: clarification. 2010-11-27 03:40:10 +00:00
z3d
56cf29c626 Readme type fix (spotted by user). 2010-11-27 03:29:40 +00:00
z3d
f6ad9be8e4 Dark tweak. 2010-11-27 03:23:22 +00:00
z3d
f56992e8e8 More readme tweaks. 2010-11-27 03:09:08 +00:00
z3d
6aa4baa2b4 Readme (eng) typo fix. 2010-11-27 02:39:35 +00:00
z3d
f0f6aeaea1 Dark tweaks. 2010-11-27 02:37:55 +00:00
z3d
31f3159991 merge of '55a577eea2afce7c3027ebe2eb4ad0032b40f9df'
and 'b48269d2804fffb770351d55a37643c0dcc508ec'
2010-11-27 02:14:26 +00:00
z3d
bf0af85714 Readme (eng) finessing. 2010-11-27 02:13:26 +00:00
privateer
c4424b4235 merge of '80ee287e0046c4751abaf3d29d9cd9e8ae26aefe'
and 'bc909db8c63cb08ea501f98b8d389496859c09b8'
2010-11-27 01:19:05 +00:00
privateer
17f0627262 - fixed wrong mail selection 2010-11-27 01:05:04 +00:00
z3d
eac4613cec Light tweak. 2010-11-27 00:44:33 +00:00
z3d
c16ea7b05b yet more readme fiddles. 2010-11-27 00:33:17 +00:00
z3d
4690ce4533 Yet more readme tweaks; update "dark" sidepanel logo. 2010-11-27 00:13:03 +00:00
z3d
14bb8bf37d Readme tweaks. 2010-11-27 00:03:04 +00:00
z3d
537ef93eb1 Readme (eng) finessing. 2010-11-26 23:42:41 +00:00
z3d
2160608a21 Readme tweaks; SnarkManager.java fix (thanks to sponge for new snark themer!) 2010-11-26 23:15:09 +00:00
z3d
ccecd72dc0 Readme (eng) typo fix. 2010-11-26 22:57:27 +00:00
z3d
25b9ce1076 merge of '0800868fb9e71ed7990ac34d125b266d4bfbe2fc'
and '3f4014962c62bb98789453c6bd7ad84da007de14'
2010-11-26 22:52:44 +00:00
z3d
0e7385a77a Readme (eng) finessing. 2010-11-26 22:51:54 +00:00
sponge
c79f0caa67 i2psnark: Don't save theme parameter if it has not changed. 2010-11-26 22:46:23 +00:00
sponge
bbfb8583c7 i2psnark: Add theme change and theme selection storage abilities. 2010-11-26 22:31:59 +00:00
z3d
b54598e9ba Readme (eng) finessing. 2010-11-26 20:02:48 +00:00
zzz
08372be34f -9 2010-11-26 15:59:45 +00:00
zzz
df55494c58 merge of 'b002d4a942128fdd4994a2cfba1c554ba9cb81d8'
and 'e6547920e2da9f540c79fcafc7ca7c82d25eae23'
2010-11-26 15:57:05 +00:00
zzz
b902656dd4 explicit merge of '1788f8361f67967c724d35db872b088e28c985d5'
and '31616535107305cf8195a51302e2b52b165f061c'
2010-11-26 15:56:27 +00:00
zzz
a0a3622f16 remove unneeded initializers 2010-11-26 15:04:58 +00:00
zzz
78a588af0e reduce UDP clock bias by rounding clock and adjusting for RTT 2010-11-26 14:57:16 +00:00
z3d
558d0284e9 Readme (eng) typo fixes. 2010-11-26 14:19:46 +00:00
zzz
e1e6db2b3c Round NTCP timestamps to reduce clock bias 2010-11-26 14:04:49 +00:00
z3d
f66fbfd0fd More readme & theme tweaks. 2010-11-26 13:45:42 +00:00
m1xxy
d7128b4db2 more changes by user 2010-11-26 11:13:17 +00:00
z3d
15382478fa Readme tweaks. 2010-11-26 10:24:14 +00:00
z3d
b21f7f7a89 Readme (eng) finesse; Dark tweaks. 2010-11-26 10:11:11 +00:00
z3d
b9567f1e54 Readme (eng): encore finesse. 2010-11-26 09:48:01 +00:00
z3d
3c256bbd30 Readme (eng): More finessing. 2010-11-26 09:26:49 +00:00
z3d
a82c50fa59 Readme (eng) finessing; Dark tweaks. 2010-11-26 09:04:54 +00:00
z3d
505d2cd469 Dark finesse. 2010-11-26 08:46:42 +00:00
z3d
8b3c072c3c Readme (eng): more textual finessing. 2010-11-26 08:26:45 +00:00
z3d
66e0a6d79d Readme (eng): more finessing. 2010-11-26 08:12:56 +00:00
z3d
bf21c28ecd Readme: jiggle service ordering. 2010-11-26 07:25:37 +00:00
z3d
5642529cc4 -8 2010-11-26 07:12:55 +00:00
z3d
06400a56ae Readme (eng): finessing. 2010-11-26 07:05:12 +00:00
z3d
d49c4f4658 Readme (eng): Tidy up layout, update text. Theme tweaks. 2010-11-26 07:00:44 +00:00
zzz
7f1ace4dbe * i2psnark: Clean up and enhance the PeerCoordinator's partial piece handling,
in preparation for more improvements
2010-11-26 00:44:00 +00:00
zzz
d37944e081 javadoc 2010-11-26 00:41:20 +00:00
zzz
358846ab04 * LogManager: When not in router context, delay creating log file until required 2010-11-26 00:37:20 +00:00
zzz
c3a2982154 * Router: Prevent NCDFE after unzipping update file 2010-11-26 00:36:07 +00:00
zzz
1197a5c8c9 reduce RouterInfo expiration again 2010-11-26 00:33:40 +00:00
zzz
9e250bc07d fix hashcode and javadocs 2010-11-26 00:32:44 +00:00
zzz
ec51ea6513 * Console: Split initialNews.xml into a file for each language;
don't copy to config dir at install.
2010-11-26 00:32:00 +00:00
z3d
ab57b55e64 Classic tweaks. 2010-11-25 18:12:39 +00:00
z3d
949f933f04 More classic tweaks. 2010-11-25 17:45:29 +00:00
z3d
8e996cd09a Console theme tweaks. 2010-11-25 17:24:56 +00:00
z3d
bab97bfbe4 Dark tweak. 2010-11-25 16:31:54 +00:00
z3d
35db17fa50 Light tweak. 2010-11-25 15:50:13 +00:00
z3d
c66b787006 Classic tweaks. 2010-11-25 14:54:46 +00:00
z3d
00aa884a72 -7 2010-11-25 13:52:24 +00:00
z3d
fc7b1ea150 merge of '60987f4b854cedf353de8adef7747f79ca24b941'
and '8760d93a324f2eb837d218bc3b7450c80bb83b70'
2010-11-25 13:43:58 +00:00
z3d
0a5ffe6651 merge of '30bd40aa8c1637256a775b418e15d0e636cc96c6'
and 'abd4faae60790075a5dd79142e3c7f8cfb15ea40'
2010-11-25 13:43:57 +00:00
z3d
e7272fce53 Console themes: Overhaul of classic and dark; fix langbox glitch on homepage. 2010-11-25 13:40:54 +00:00
m1xxy
b9c36e436d some changes to portuguese readme 2010-11-25 11:37:19 +00:00
m1xxy
a8a608c5c5 br and es readme tweaks 2010-11-24 22:34:56 +00:00
HungryHobo
ef92123e00 0.8.1-6 2010-11-24 17:46:23 +00:00
HungryHobo
58da5d7942 * Don't use bash explicitly
* Don't put the signer's name into the SignWith field, use the email address instead to avoid problems with spaces
2010-11-24 17:45:13 +00:00
zzz
838da762f8 -6 2010-11-24 16:47:50 +00:00
zzz
9c96c07f3e merge of 'bbaea7567520aced60f19b571f63c11cbb3b1d76'
and 'e7bbb1ca66df6fb49b2f1fcb554e8077dd488fb2'
2010-11-24 16:45:43 +00:00
zzz
9053a86eb0 br->pt 2010-11-24 16:45:28 +00:00
zzz
d5b079faa8 Message cleanup 2010-11-24 16:41:19 +00:00
zzz
8228365d4b * Router:
- Remove global lock on accessing config
      - Add global lock on reading/writing config file
2010-11-24 16:40:13 +00:00
zzz
a8b602bc54 * SimpleDataStructure: Fix problem in fromBase64() that
manifested itself as a configtunnels.jsp bug
2010-11-24 15:06:49 +00:00
zzz
0b59af6551 * i2psnark:
- Prevent dup requests during end game
        (ticket 331 - thanks sponge and Oct!)
2010-11-24 15:04:52 +00:00
zzz
90490cb65d cleanup; limit concurrent renderings to conserve memory 2010-11-24 15:01:14 +00:00
zzz
af519732c4 save some info we might need later 2010-11-24 14:59:27 +00:00
zzz
868f5b1c38 remove dup log 2010-11-24 14:58:40 +00:00
zzz
55db8bf3f6 save p param across posts 2010-11-24 14:56:58 +00:00
zzz
18a90516b3 javadoc 2010-11-24 14:56:07 +00:00
sponge
5f3834d398 Slackware, fix rc.i2p, bad logic. 2010-11-24 14:55:53 +00:00
zzz
4dfac0846b add pt, move readme_br to _pt 2010-11-24 14:55:16 +00:00
zzz
ffee32535e add more info about trac 2010-11-24 14:53:41 +00:00
zzz
1b59135b4a javadoc, and comment out a test method 2010-11-24 14:53:24 +00:00
sponge
8b5c0a2db1 Plugin: ticket 104 Fix webapp isRunning to check ALL webapps.
The only defecency is that if one is running, that it considers the
      entire pliugin to be running. I'm not sure if that is a good thing
      or a bad thing, but the other code checks threads that way.
2010-11-24 14:31:54 +00:00
z3d
dec1a9d77d Readme.html: Remove links to tino/perv's eepsite status sites (requested by zzz); more tuneups. 2010-11-23 21:30:08 +00:00
z3d
b39d1c7322 Readme.html: finessing. 2010-11-23 20:40:12 +00:00
z3d
19696e1ec1 Readme.html: Add perv and tino eepsite lists; add i2plugins; add target="_blank" to all external links. 2010-11-23 20:08:01 +00:00
z3d
d6a6836d90 merge of '3b6c4d6af6fae83cc9b7d42e8515804ae48ec675'
and '799a00a4929a59478c534a56cce350cdb9a042e0'
2010-11-23 13:54:18 +00:00
m1xxy
53efb4e046 changes to spanish snark by user 2010-11-23 06:30:04 +00:00
m1xxy
fa4379aef1 Portuguese, thx to user 2010-11-22 22:30:11 +00:00
m1xxy
591e531ab6 Kleinschreibung 2010-11-22 22:24:09 +00:00
m1xxy
c41a0c49b3 merge of '09a1ef8a35181c9ebdca5244237767f3eedc3ac0'
and 'ff29f16d54e144a5bdc987ddb29a1b9063742e40'
2010-11-22 17:07:28 +00:00
m1xxy
7c37590800 2010-11-22 17:06:57 +00:00
zzz
e4e0697ea8 -4 2010-11-22 01:17:26 +00:00
zzz
ee831106b7 merge of 'c6ad7f9d5bc5afefd248c4fc8fa5266642e18143'
and 'cbd2b39bbf04f7e25bcea99f213cbad1c323e445'
2010-11-22 01:16:25 +00:00
zzz
502f247d08 update trac message 2010-11-22 01:12:00 +00:00
zzz
ad96c8498d more conversion to POST 2010-11-22 01:03:35 +00:00
m1xxy
705598d66a quote=user: holding back further work until dr|z3d complies with his promise 2010-11-21 23:12:11 +00:00
zzz
3e52d6959b require POST where we can 2010-11-21 23:05:14 +00:00
m1xxy
76bc6f5aee two missing spaces in i2psnark 2010-11-21 22:29:53 +00:00
zzz
6c19e7e399 * i2psnark:
- Defer piece loading until required
      - Stub out Extension message support
2010-11-21 21:19:12 +00:00
zzz
b5ae626425 sort tweak 2010-11-21 20:49:45 +00:00
zzz
d710da5c11 add note 2010-11-21 20:48:17 +00:00
zzz
883fb2cb4a log tweak 2010-11-21 20:47:59 +00:00
zzz
2a34ea8356 * Console:
- Convert GraphHelper to a FormHandler
      - Require POST for all forms
      - Change the way we store the Writer to prevent problems
      - Fix bonus setting on configpeer.jsp
      - More ".jsp" removal
2010-11-21 20:46:48 +00:00
zzz
9e8af7367e * Addressbook: Fix rename error on Windows (tkt 323 - thanks RN!) 2010-11-21 20:40:42 +00:00
zzz
106af9967a * SSLEepGet, Reseeder:
- Implement additional CA loading
      - Provide facility to reuse SSL state for speed
      - Provide facility to store previously untrusted certificates
      - Add SSL reseed hosts, prefer them by default
      - Reseed message cleanup
    * build.xml:
      - Add www.cacert.org cert to the installer and updater so
        SSL on a.netdb.i2p2.de and c.netdb.i2p2.de will work
      - Cleanup, fix distclean error in older ants.
2010-11-21 20:37:49 +00:00
m1xxy
c8cad6ab79 fixed a few typos 2010-11-21 18:40:30 +00:00
m1xxy
d8139cb19e further changes to eepsite, e.g. s/link drücken/link klicken 2010-11-21 12:39:37 +00:00
m1xxy
7a469b048e merge of '1ab0d0ba04d993e3f1101e599cecbcdc3950a26d'
and '26e69d318672e267117c74a736c1ab3d38215c20'
2010-11-20 16:48:40 +00:00
m1xxy
b23d6c9dbe insert a missing space 2010-11-20 16:47:18 +00:00
zzz
d23fdd6b4c -3 2010-11-19 22:47:45 +00:00
zzz
49325d491d merge of '50335c064a9992f4ba8707d62d35bbbbe752d231'
and 'b93c1c7b2b01fc43af5bc07470d9997f3edba6da'
2010-11-19 22:46:27 +00:00
zzz
635b53c329 fix ant distclean javadoc 2010-11-19 22:30:41 +00:00
zzz
72d2137e9b javadoc fix 2010-11-19 22:07:29 +00:00
zzz
c06198491e always have as many recent as active 2010-11-19 21:13:35 +00:00
zzz
9b69dad06b * Addressbook
- Store last-fetched time so we don't always fetch subscriptions after restart
      - Randomize first fetch time
      - Make most classes package private
2010-11-19 21:12:45 +00:00
m1xxy
1a8406e0f7 merge of 'cdf6b7afd6c4244142f0a24fda0a9603ea117767'
and 'f5d8fb56c10dc0007901ed64a84a5cba32a3ca92'
2010-11-19 19:26:47 +00:00
m1xxy
509befc912 removed some strange-looking strings in French router console translation that stroke my eye, have not read through all of it tho; change some capitalizations in de and de eepsite 2010-11-19 19:17:07 +00:00
z3d
e73439d876 Console: New favicon.ico 2010-11-19 19:02:05 +00:00
zzz
729aedee5f * News:
- Store news last-fetched time so we don't always fetch news after restart
      - Don't include news in the updater
2010-11-19 18:34:00 +00:00
m1xxy
765d4b8563 update languages 2010-11-19 17:58:30 +00:00
zzz
6b0c931200 change buttons from GET to POST 2010-11-19 16:42:23 +00:00
zzz
dd39f3f244 i2ptunnel jsp cleanup 2010-11-19 16:14:14 +00:00
zzz
af4a285e5b fix small confignav problem 2010-11-19 15:32:31 +00:00
zzz
166f378f2f clean up more urls and POST self-references 2010-11-19 15:23:25 +00:00
z3d
9d037911d0 Eepsite Help: Add some new flags, tweak layout, finesse German. 2010-11-19 15:01:26 +00:00
z3d
73baec8539 merge of '7665dfe8f38eaf14d608493cb893b2dffaba49aa'
and 'edc923fb03834a90710c72b8a3fb206cfb904e86'
2010-11-19 14:45:49 +00:00
z3d
118872ab69 merge of '75fac120e4d13f521c4a863604f331b845a2d7e4'
and 'f0fab315b6a44d956c29a25bb527e7974ea62088'
2010-11-19 14:45:47 +00:00
zzz
f0ac96cab1 Increase i2ptunnel nonce queue size again 2010-11-19 14:42:10 +00:00
zzz
4545a98968 More work on error propagation and improving log messages in i2ptunnel and I2CP client 2010-11-19 14:41:26 +00:00
z3d
0ba6299655 Readme: Insert missing </div> to fix positional issues with langbar. 2010-11-19 14:41:08 +00:00
m1xxy
e32e316146 convert period to exclamation mark 2010-11-19 07:16:04 +00:00
zzz
e940f51599 * SecureFile: New class, catch places that were missed,
add i2p.insecureFiles option to disable (default false)
2010-11-19 00:40:33 +00:00
zzz
50d9080e26 add note 2010-11-19 00:36:24 +00:00
HungryHobo
6836b548af Comments 2010-11-18 23:52:43 +00:00
m1xxy
457e1d293a update 2010-11-18 22:55:45 +00:00
m1xxy
11807df8b3 merge of '09e7a6657a746f06face3afe1374efc8179d9739'
and '21d86fc1f8deb605adc6f6a7022e644e1f4c8b00'
2010-11-18 22:49:28 +00:00
m1xxy
96ff36c159 fix a line break and too long seconds 2010-11-18 22:47:34 +00:00
HungryHobo
da782c07a4 Add debian/source/format (lintian: missing-debian-source-format) 2010-11-18 20:58:37 +00:00
HungryHobo
b32399ac60 0.8.1 2010-11-18 20:58:04 +00:00
HungryHobo
f1e36f7fd0 Create Debian packages in debian/packages/ instead of ../ 2010-11-18 20:56:42 +00:00
zzz
1cad02c461 remove jrandom signing key as it may no longer be secure 2010-11-18 19:27:37 +00:00
m1xxy
b56563deee new router console strings, leaving 'rolling avg' for next round 2010-11-18 19:17:02 +00:00
zzz
81d885c5a4 postman b32 take 2; recognize oga and ogv 2010-11-18 15:02:29 +00:00
m1xxy
ad3039390d more proxy translation 2010-11-18 11:53:08 +00:00
m1xxy
365e0f093d 2010-11-18 09:18:15 +00:00
zzz
138be42aa5 bye .jsp part 2 2010-11-17 22:26:31 +00:00
zzz
8a385ffc32 recognize postman b32 2010-11-17 22:19:13 +00:00
zzz
995c736a71 peers.jsp fixups 2010-11-17 22:15:45 +00:00
zzz
a9801766e5 * PrivateKeyFile: Speedups and better messages 2010-11-17 22:14:55 +00:00
zzz
6544e135b2 add red clock 2010-11-17 16:23:40 +00:00
zzz
a71b379ff8 comment out distclean deb files again 2010-11-17 16:13:59 +00:00
zzz
2f880f7b5b propagate from branch 'i2p.i2p.zzz.test4' (head 3569f7d0608498cadafc88e87a0ad2b18c44dfb6)
to branch 'i2p.i2p' (head ddc9be27c47878e472d5b6c281cccb6094c42c9a)
2010-11-17 16:09:19 +00:00
zzz
f698ef93e8 * I2PTunnel SOCKS and SOCKS IRC clients:
- Add SOCKS 5 outproxy support, with username/password authorization
    * I2PTunnel
      - Index page outproxy display cleanup
2010-11-17 15:47:00 +00:00
zzz
bf0275ddcb * I2PTunnel: Improve messages when starting and stopping tunnels, add some tags 2010-11-17 14:27:32 +00:00
zzz
e68a3fb856 * Streaming: Fix bug causing read() to incorrectly return EOF 2010-11-17 14:26:24 +00:00
m1xxy
b9a6dfbcda a missing comma in i2psnark, prolly others still missing 2010-11-17 00:03:38 +00:00
m1xxy
28f790bbe7 further tiny de tweaks 2010-11-16 18:52:03 +00:00
m1xxy
1becd42695 changes to spanish by user 2010-11-16 18:32:42 +00:00
m1xxy
d6f80a7b77 tweaks to French i2psnark translation by albat and user 2010-11-16 18:25:58 +00:00
zzz
bdbbe30c2c bump to -1 after merge of stuff that missed the release 2010-11-15 13:27:24 +00:00
zzz
b0ae907a86 merge of '1d65e621dc6cf1d3558c33ec81ac8dc5820c210e'
and '9572100b83b95246d97f9879011be63898ac1e52'
2010-11-15 13:26:04 +00:00
zzz
4078c70caa news header fix 2010-11-15 13:01:06 +00:00
HungryHobo
fb6560db40 merge of '2eb6f45d531fc66bce57696bd27ae4d2ea9cd2a0'
and '84303e0952347926ec08fcea629bb0b27f9b95dd'
2010-11-15 00:49:36 +00:00
zzz
10aed35b08 0.8.1 2010-11-15 00:23:00 +00:00
HungryHobo
cbf0239c23 Fix lintian error: no-standards-version-field 2010-11-15 00:18:31 +00:00
HungryHobo
a7c50fcfd9 Make maintainer in debian/changelog the same as in debian/control (lintian: changelog-should-mention-nmu) 2010-11-15 00:13:11 +00:00
HungryHobo
a598d9019c strip binaries in debian package (lintian: unstripped-binary-or-object) 2010-11-15 00:07:40 +00:00
m1xxy
a91d9bc68f proxy Err pages translation de 2010-11-14 23:59:01 +00:00
zzz
355ca7b2f7 tweaks after review 2010-11-14 23:58:13 +00:00
HungryHobo
e963c3d3a2 Add binary-arch and binary-indep targets (lintian: debian-rules-missing-required-target) 2010-11-14 23:57:36 +00:00
HungryHobo
3b4371ad4b Replace libc6 dependency with shlibs:Depends (lintian: package-depends-on-hardcoded-libc) 2010-11-14 23:55:03 +00:00
m1xxy
2121b04f31 merge of '1e02b9123df580c44b0fa30918003bc8cf8030a4'
and 'c65ae88fa8b668ccd972d6a0bafe7843ea487285'
2010-11-14 19:25:06 +00:00
m1xxy
2420373389 language names consistency fix 2010-11-14 19:14:31 +00:00
hiddenz
235f6e0383 merge of '582904768901629443730b9763abb65e8ac8dd74'
and '8e94fe72b25ee4167620078c94890ca496fba9ad'
2010-11-14 18:40:58 +00:00
hiddenz
3f7d432f91 routerconsole: update russian translation
- Change translation of some terms:
  + тред -> поток
  + журнал -> лог
  + аптайм -> время работы
- use lowercase for second word where needed
- Reorder words where needed

These things was discussed on irc #ru
2010-11-14 18:38:23 +00:00
hiddenz
894e649be9 routerconsole: russian translation fixes 2010-11-14 17:35:52 +00:00
hiddenz
388767258a i2psnark: update russian translation 2010-11-14 16:27:27 +00:00
zzz
f3307d6508 * Addressbook:
- Try to save files safely
      - Catch bad B64 lengths
2010-11-14 15:05:24 +00:00
zzz
c29a275969 summary bar spacing cleanup 2010-11-14 15:03:50 +00:00
zzz
c890f61d0b javadoc 2010-11-14 15:01:52 +00:00
zzz
1e0e24826e concurrent 2010-11-14 15:01:23 +00:00
hiddenz
d6ea9cb0a4 i2ptunnel: update russian translation 2010-11-14 14:57:47 +00:00
zzz
dc6fc0185c final 2010-11-14 14:56:54 +00:00
zzz
1d627371ce todo comment 2010-11-14 14:55:58 +00:00
zzz
d3b05f44d5 cleanups 2010-11-14 14:54:18 +00:00
zzz
581b915748 Call session.propogateError() on reception of SessionStatusMessage with bad status or DisconnectMessage 2010-11-14 14:53:30 +00:00
zzz
e293b25bb7 I2CP username/pw auth (client side) 2010-11-14 14:50:45 +00:00
zzz
23005a82b1 I2CP username/pw auth (router side) 2010-11-14 14:49:26 +00:00
zzz
d47dcddb9b send I2CP DisconnectMessage at router shutdown 2010-11-14 14:47:43 +00:00
zzz
cd621f2b4b * I2PTunnel SOCKS and SOCKS IRC clients:
- Add local proxy username/password authorization
2010-11-14 14:22:45 +00:00
zzz
7cbf74d3f2 * I2PTunnel HTTP and Connect clients:
- Shim in a new abstract superclass I2PTunnelHTTPClientBase for common code
      - Add local proxy username/password authorization
      - Add outproxy username/password authorization
      - Filter hop-by-hop Proxy headers appropriately
2010-11-14 14:18:43 +00:00
zzz
7967653dd1 * DataStructures:
- Shim in 3 new abstract classes
        SimpleDataStructure, KeysAndCert, and DatabaseEntry

===========

Right now, everything in net.i2p.data extends DataStructureImpl.


There are several goals for adding some intermediate abstract classes,
between DataStructureImpl and the concrete classes:


1) Merge common code
2) Make the simple cases (a single byte array) more efficient
   by adding a common base class.
   I'm calling this one SimpleDataStructure.
3) Make a common base class for Destination and RouterIdentity
   since they are almost exactly the same thing.
   Consolidate the getters/setters and hash functions here.
   I'm calling this one KeysAndCert.
4) Make a common base class for LeaseSet and RouterInfo so
   so netDb and I2NP can handle them easier, without doing
   "instanceof" all over the place.
   Consolidate the hash, signature, and routing key functions here.
   I'm calling this one DatabaseEntry.
5) Make it easier to add more object caching.


The additional classes are retrofit
above many of the data types:


DataStructureImpl (unchanged)
-------------------
	ByteArray
	Certificate
	Lease
	Payload
	RouterAddress
	TunnelId


	SimpleDataStructure (new)
	-------------------------
		Hash
		PrivateKey
		PublicKey
		SessionKey
		SessionTag (was ByteArray)
		Signature
		SigningPrivateKey
		SigningPublicKey


	KeysAndCert (new)
	-----------------
		Destination
		RouterIdentity


	DatabaseEntry (new)
	-------------------
		LeaseSet
		RouterInfo
2010-11-14 14:09:58 +00:00
zzz
ad060c5d5d remove unused TunnelId methods 2010-11-14 14:00:39 +00:00
m1xxy
9af33974eb merge of '9e5fa2ede2d44dd05b58b29796cb86a510628fa2'
and 'd0a4b4ea6faa776eb1e35049ffdc0fb0beee9135'
2010-11-13 23:00:10 +00:00
m1xxy
fdbfa00d96 fix missing </a> 2010-11-13 22:43:20 +00:00
hiddenz
e844cf25c2 routerconsole: update russian translation 2010-11-13 22:20:30 +00:00
HungryHobo
4df05f69b1 merge of '3aff7e5f43f96e1909cffca3b9c608bb6b02af53'
and '9dc9aae56898fbe4bb03c860f00dac9b8a5552b5'
2010-11-13 21:54:48 +00:00
m1xxy
c52693d2ac little translation tweaks in i2psnark 2010-11-13 20:02:04 +00:00
HungryHobo
8d2a75bc01 Add man pages for eepget and i2prouter 2010-11-13 17:58:05 +00:00
HungryHobo
5fe654e7e8 Abort if any command in the script exits with an error (lintian: maintainer-script-ignores-errors) 2010-11-13 17:55:34 +00:00
HungryHobo
cd741439d9 merge of '83f0017029b25b67b4d90694eba5ceefb9f006f9'
and 'ae9bcaf1a7c197b462162c4513161894de6c658a'
2010-11-13 17:25:25 +00:00
m1xxy
bdff919d3f only updating a flag on readme 2010-11-13 16:23:31 +00:00
zzz
f4b49f7425 change low mem error to warn 2010-11-13 12:06:16 +00:00
zzz
db7e4a273b static 2010-11-13 12:05:49 +00:00
m1xxy
42f6b9e24b merge of 'b6f941cc4c3eb51d9106dfdf35abdd7f3d1199af'
and 'ed834a4da30a6a913ab0145cd76519e5eaa969d2'
2010-11-13 10:53:30 +00:00
m1xxy
ad3ae84083 French translation Nachtrag 2010-11-13 10:53:14 +00:00
m1xxy
a4c9397db0 French translation of i2psnark done by Redzara. Thx, redzara\! 2010-11-13 09:56:43 +00:00
z3d
5380879aba I2PSnark: Update stopped.png 2010-11-13 08:50:46 +00:00
HungryHobo
eda1f8d640 merge of '89b2dc0430e50fd1ce78ab07cd3545aded81fee9'
and 'dcba57e8260ad530685ca665724566533964a7b4'
2010-11-13 04:14:13 +00:00
HungryHobo
88e98f0f67 Don't call the init script directly, use invoke-rc.d (lintian: maintainer-script-calls-init-script-directly) 2010-11-13 04:08:56 +00:00
m1xxy
2faa60ee59 update eepsite help 2010-11-13 02:43:35 +00:00
HungryHobo
b614d14037 merge of '4fff03e3acecbfb131a884b6c151967978058c49'
and '7ec0520d4bb67df2b9c378aab53bffbf8dcb222b'
2010-11-13 01:36:25 +00:00
m1xxy
d9bf826baf initialNews.xml fix; i2psnark translation tuning 2010-11-13 01:30:02 +00:00
HungryHobo
2152c5f6c9 Use a variable for /tmp to make lintian happy (possibly-insecure-handling-of-tmp-files-in-maintainer-script) 2010-11-13 00:39:55 +00:00
HungryHobo
0d23e37124 Add shebang to script 2010-11-13 00:30:11 +00:00
HungryHobo
fddf32a6ca * Stop service at runlevels 0 and 6 (lintian: init.d-script-possible-missing-stop)
* Add force-reload option, same as restart (lintian: init.d-script-does-not-implement-required-option)
2010-11-13 00:28:30 +00:00
HungryHobo
a07339e1ff Remove rc.d files in postrm, not in prerm (fixes lintian errors prerm-calls-updaterc.d and postrm-does-not-call-updaterc.d-for-init.d-script) 2010-11-13 00:03:13 +00:00
m1xxy
c5a6c5d412 merge of '963a4636469adb55ac3981048b32011865bb4faa'
and 'cdac59d49a839e82c626130a576b12a1297f981e'
2010-11-13 00:02:02 +00:00
m1xxy
7e17ac989b adding stub 2010-11-12 23:53:33 +00:00
HungryHobo
7b5e331038 Put a name and email in the Maintainer field 2010-11-12 23:28:25 +00:00
HungryHobo
ae101f6cad Reorganize the Debian directory structure to conform to their packaging policy. This brings the number of Lintian errors+warning
s down from 383 to 16.
2010-11-12 22:57:59 +00:00
z3d
98f559c9c0 I2PSnark: More width futzing. Please report any layout breakage (wrapping lines in main torrent table). 2010-11-12 19:08:47 +00:00
z3d
d368bb8ae0 I2PSnark: More width futzage. 2010-11-12 13:20:42 +00:00
z3d
33932eb373 I2PSnark: TorrentName width tuneup. 2010-11-12 12:58:17 +00:00
z3d
7d6e237183 merge of 'bc9f7e74001104c203687a91535b414228b5184b'
and 'f0ebb51ab350759843e67cdc74a8ec8158fe5ac6'
2010-11-12 12:28:52 +00:00
z3d
056fb5ea88 I2PSnark: Indentation cleanups. 2010-11-12 12:27:10 +00:00
m1xxy
92d013752a merge of 'c51af7655557d0a98ec7561a4f434c63d5f26f41'
and 'e42b35ff366e0c56916caaeec4a14f17ac95a0eb'
2010-11-12 09:03:51 +00:00
m1xxy
a9daf8fc8f bump bote to router console start page 2010-11-12 09:03:16 +00:00
HungryHobo
c3aa84f961 Run includedeb and include on each file individually, reprepro can't do multiple files 2010-11-12 05:09:06 +00:00
HungryHobo
b4524c67d5 Make separate i386 and amd64 packages, this fixes the arch-independent-package-contains-binary-or-object lintian error 2010-11-12 04:04:27 +00:00
m1xxy
11b69ee121 disapproval of revision '7c7c3832c57db0fee96000f6cf612d1443b0fc85' 2010-11-12 01:25:49 +00:00
m1xxy
be3330d84f bump bote to readme.hmtl 2010-11-12 00:49:05 +00:00
HungryHobo
9439477799 merge of '3643017f592675aa1170acb97e64ad78fbe9405c'
and 'ca29fd016d218f636d2cc844d46d6a25ca9ff5c6'
2010-11-11 22:40:14 +00:00
m1xxy
826efdf767 translation of dr|z3d's newly added stuff and more consitency fixes 2010-11-11 10:01:07 +00:00
z3d
7ef35e0284 I2PSnark: Do our level best to prevent stuff from wrapping and breaking the table layout; bump to -18rc. 2010-11-11 07:02:42 +00:00
z3d
0324bc4eec Bump to -17rc. 2010-11-11 06:50:15 +00:00
z3d
f157471ac1 I2PSnark: Increase min-width for status column to prevent column header from wrapping. 2010-11-11 06:49:14 +00:00
z3d
416e7825a8 I2PSnark: Remove thinspaces for download column. 2010-11-11 06:40:18 +00:00
z3d
6b12d26388 I2PSnark: Css tweak. 2010-11-11 06:32:16 +00:00
z3d
0adac224fb I2PSnark: Parent dir icon (up.png) tweak. 2010-11-11 06:28:41 +00:00
z3d
6935d7361a Bump to -16rc. 2010-11-11 06:15:53 +00:00
z3d
05409bae6e I2PSnark: Revert the regression, hopefully cunningly sidestepping conflicts. 2010-11-11 06:12:25 +00:00
z3d
283e915514 merge of '9ef5f8dbdf741e0d3f6f88061efff16e14d9182a'
and 'b44b28fa2d4279996e0adbc143968ec132faed8d'
2010-11-11 05:20:18 +00:00
z3d
676d84a081 I2PSnark: CSS whitespace/tab cleanups. 2010-11-11 03:58:20 +00:00
z3d
9f6e6cd54d I2PSnark: Add details_nolink.png icon for trackers that don't work with infohash extraction.
Mousever should provide minimal info, eg: tracker id.
2010-11-11 02:43:07 +00:00
z3d
dc51d694db Bump to -15rc. 2010-11-11 01:34:29 +00:00
z3d
0f63158f50 I2PSnark: Main torrent table tidyups and tweaks. 2010-11-11 01:33:56 +00:00
z3d
903d27ec0d Bump to -14rc. 2010-11-11 01:01:45 +00:00
z3d
5d9ed45cbd I2PSnark: Tweak details.png 2010-11-11 00:59:23 +00:00
z3d
7c0ef0ab80 I2PSnark: Tidyups. 2010-11-10 22:15:13 +00:00
HungryHobo
bda00e18fe * Fix build dependencies for Debian
* Add dependency on libc6 which fixes the lintian warning missing-dependency-on-libc
2010-11-10 21:01:52 +00:00
z3d
49fb6c59d1 Bump to -13rc. 2010-11-10 21:00:49 +00:00
z3d
224aa5fd9c I2PSnark: File manager cleanups. 2010-11-10 20:56:37 +00:00
z3d
25e21ffb1e I2PSnark: Screenlog padding fix. 2010-11-10 18:15:15 +00:00
z3d
0165c6068a Bump to -12rc. 2010-11-10 17:59:27 +00:00
z3d
585339e0d4 I2PSnark: All the goodness from the disapproved branch + visual fixes. 2010-11-10 17:56:33 +00:00
z3d
83ae568d38 I2PSnark: Fix Rate tag. Spotted by mixxy. 2010-11-10 14:53:15 +00:00
z3d
b323408cee merge of '285a9a021659672b12861eea3c150d47b5025275'
and 'a90a0715f156a732cf039bd2df9bbc3d90e82693'
2010-11-10 14:37:57 +00:00
z3d
71707bf0c0 disapproval of revision 'ffe706fb236d2cd14241d22dc6e6203964f8bc31' 2010-11-10 14:37:39 +00:00
m1xxy
7db5340159 merge of '96b28bcad599dea550230cc8cba4d7bce7f5fa68'
and 'a396094617a5124882fc16e11466375fcc4f3047'
2010-11-10 14:11:45 +00:00
m1xxy
dee2f2431c cinsistency fix 2010-11-10 14:09:26 +00:00
m1xxy
0b0fa04210 merge of '3dfa2ea9f44e204ca76d700e01ae09cda54c6b6a'
and 'a90a0715f156a732cf039bd2df9bbc3d90e82693'
2010-11-10 13:41:59 +00:00
m1xxy
18374fe426 German translation cleanups 2010-11-10 13:29:33 +00:00
HungryHobo
ab432e14ee Fail if repository cannot be created 2010-11-09 22:19:32 +00:00
HungryHobo
5d9a7b9452 Add changelog to .deb 2010-11-09 21:34:44 +00:00
HungryHobo
e9af7406c6 Update changelog 2010-11-09 21:30:32 +00:00
zzz
20e2e20212 * I2CP: Fix NPE caused by null session options (seen in i2pbote) 2010-11-08 16:13:43 +00:00
HungryHobo
7897df5544 Improve the Debian copyright file, see http://lists.debian.org/debian-legal/2003/12/msg00194.html 2010-11-08 03:23:30 +00:00
HungryHobo
0e9f0a741e Print destination in b64 2010-11-08 03:23:19 +00:00
zzz
31ff9b2747 update javadoc links and titles 2010-11-07 20:25:29 +00:00
zzz
dcd915457b minor javadoc fix 2010-11-07 20:23:45 +00:00
zzz
454a5c5286 explicit merge of '14597ede957582a9ca29df867f1565479c64888b'
and '6c0d71283dd65aea1fe1baad14ca57855808dad8'
2010-11-07 20:22:44 +00:00
m1xxy
168a4ca6f9 minor translation corrections #3 2010-11-07 00:48:22 +00:00
z3d
6e48ecb9ce I2PSnark: Fix syntax errors; tweak css. 2010-11-06 14:21:22 +00:00
zzz
959e57e755 RIP crstrack 2010-11-06 13:26:57 +00:00
zzz
0e53445e91 * logs.jsp: Format multiline messages better 2010-11-06 12:34:53 +00:00
zzz
3ee85fed30 * Stats: Improve Frequency, enable coalescing; cleanup and javadocs
* stats.jsp: Cleanup, more tagging, hide obscure stuff unless ?f=1
2010-11-06 12:33:53 +00:00
zzz
010a1fde3f * Console: Display durations with new formatDuration2() 2010-11-06 12:28:38 +00:00
HungryHobo
c2349662e7 Minor things 2010-11-06 05:40:24 +00:00
HungryHobo
43c7cc0893 Auto download jetty in the debian and debian-source targets 2010-11-06 05:38:00 +00:00
HungryHobo
d64a2b0306 * Add debianrepo target
* Change the debian target to build binary and source, add a debian-binary target
2010-11-06 04:51:11 +00:00
zzz
1bc563832e propagate from branch 'i2p.i2p' (head 7f26a3df7f04d3c069c63b4633871bd7676f6167)
to branch 'i2p.i2p.zzz.test4' (head 91572937612227b99f41e7e170ae38574a001e7b)
2010-11-05 12:46:59 +00:00
zzz
1f48c6c03d deprecate unused toDate(Date) 2010-11-05 12:46:41 +00:00
m1xxy
50aca88438 corrections of translation, mainly capitalization, ß and white spaces, some grammar fixes 2010-11-05 10:30:22 +00:00
HungryHobo
be5bd43194 Debian package: Fix purge with no prior remove (rev. 9a8fca24502aa8933793f2bad48e327596a2c0d4 only fixed remove, then purge) 2010-11-05 07:03:45 +00:00
m1xxy
8894aa7d38 minor translation corrections #2 2010-11-04 23:29:45 +00:00
m1xxy
092d29fe56 minor translation corrections 2010-11-04 08:55:25 +00:00
HungryHobo
8593931171 If the working directory contains only a plugins/ subdir, initialize it like it is empty 2010-11-04 06:49:12 +00:00
HungryHobo
77e0cb94d3 merge of '01966a37ff4e50e48ab6eeb9d215baa8b75fc46d'
and '85cbdd70a9896ae9b2257bfe8f25f045b1cd0b2d'
2010-11-04 04:24:23 +00:00
zzz
2b2c3cf118 snark tweaks 2010-11-03 22:21:10 +00:00
zzz
be308a0444 merge of '398a24f487b61ef778a2e849660e953ef7e43b39'
and '598d00efae4c9b675b64fd626bc2eab2b921e0c5'
2010-11-03 16:04:14 +00:00
z3d
9b39f02ce5 I2PSnark: Relocate errant "." 2010-11-02 14:07:25 +00:00
z3d
7109061ee0 merge of '4dfe5728ed4951d32f89e2fddbdcdfc3b4755cad'
and '62005c74e58b5fdbaf4659ffb65392ecfbd8bc0a'
2010-11-02 13:49:03 +00:00
z3d
f71dd25b3c I2PSnark: Relocate a pesky \n. 2010-11-02 13:48:11 +00:00
z3d
012fbe3a45 I2PSnark: Relocate </code> to its rightful place. 2010-11-02 13:22:48 +00:00
HungryHobo
853f941d88 merge of '598d00efae4c9b675b64fd626bc2eab2b921e0c5'
and 'd38686d88680521e54d7bcb8be24e21d252eb946'
2010-11-02 04:00:43 +00:00
HungryHobo
c03abb50d3 merge of '8c4c57f191c33a31bc69564888c9851f9042438c'
and '9c5d0b4cdfa76234e6ac9fbfd0ce753748104f47'
2010-11-02 03:51:00 +00:00
HungryHobo
94bc3c3503 merge of '1da5a6b3f2f42d9ddbe6b0a64e3c27313d61d86a'
and '5784df5facdf6e194dc3c052b2527a8c63c96c0f'
2010-11-02 03:49:06 +00:00
HungryHobo
252473d7cf merge of '5784df5facdf6e194dc3c052b2527a8c63c96c0f'
and '9c5d0b4cdfa76234e6ac9fbfd0ce753748104f47'
2010-11-01 22:09:52 +00:00
z3d
6eb8cbfacc I2PSnark: CSS refinements. 2010-11-01 22:08:05 +00:00
zzz
ddc86b54c7 fix snark rates 3x too low 2010-11-01 22:04:10 +00:00
zzz
3678aa157e * i2psnark:
- Limit number of parallel requests of a single piece when in the end game
      - Shorten and weight the speed tracker so the display is more
        reflective of current speed
2010-11-01 14:35:01 +00:00
z3d
4d7a77d318 I2PSnark: Bug fix. 2010-11-01 14:33:10 +00:00
zzz
8d13bcbac0 discourage b32 2010-11-01 14:30:57 +00:00
zzz
2f54ec61bd logging tweak 2010-11-01 14:30:24 +00:00
HungryHobo
af541662f3 Add get-orig-source rule as required by Ubuntu, see https://wiki.ubuntu.com/UbuntuDevelopment/CodeReviews#NewPackage 2010-10-31 21:13:53 +00:00
HungryHobo
3e2c530281 Fix error message with dpkg --purge 2010-10-31 19:54:49 +00:00
HungryHobo
ff5b7950f1 Debian package:
* Make eepget, i2prouter, and i2psvc world-executable
 * Auto-start I2P after installation
2010-10-31 19:52:28 +00:00
HungryHobo
148ce25af7 Print an error if /etc/init.d/i2p is run as non-root so Ubuntu users aren't asked for a non-existing root password 2010-10-31 19:48:41 +00:00
HungryHobo
56ef384595 Make /usr/bin/eepget and /usr/bin/i2prouter symlinks 2010-10-31 19:44:33 +00:00
HungryHobo
ea24f3ba6d Fix dependencies for Ubuntu 2010-10-31 19:41:55 +00:00
zzz
ba4f6608e4 update nbsp comment 2010-10-31 14:52:21 +00:00
zzz
07aa07981d * logs.jsp: Add message if wrapper log not found
(ticket #103)
2010-10-31 14:52:09 +00:00
zzz
0afabbd609 Add synch to fix race causing AIOOBE
http://forum.i2p/viewtopic.php?t=5061
2010-10-31 14:36:56 +00:00
zzz
2ea3f9b9bb parse log limit with current locale (ticket 118) 2010-10-31 14:33:31 +00:00
z3d
35a8c703a7 I2PSnark: Unitalicize remaining download amount. 2010-10-30 20:24:24 +00:00
z3d
d0855ee892 I2PSnark: Status icon updates. 2010-10-30 19:32:46 +00:00
z3d
e95b41511a I2PSnark: Add status icons, refine css. 2010-10-30 16:34:04 +00:00
zzz
30a5c4907b -6; history for this head 2010-10-30 15:50:03 +00:00
zzz
f170baab3f - Delay during StopAll so we don't close the tunnel before the
stopped announces go out and reopen it
- Logging tweaks
2010-10-30 15:30:14 +00:00
zzz
643687472a - Only add wanted pieces to wanted list at startup
- Make sure lastRequest is null when it should be
- Logging tweaks
2010-10-30 15:28:29 +00:00
zzz
c76058efc3 send &compact=1 to keep opentracker happy 2010-10-30 14:17:09 +00:00
zzz
502cf72653 fix nbsp screwing up POST 2010-10-30 00:38:08 +00:00
zzz
9baa6e7bc8 update requests after changing priorities 2010-10-29 20:31:07 +00:00
zzz
7efb0fa7ed * i2psnark:
- Priority mapping bugfix
      - Close files as we go when creating/checking
        so we don't run out of file descriptors
2010-10-29 17:32:05 +00:00
zzz
571ad83e03 use nbsp in formatSize2() 2010-10-27 14:22:53 +00:00
zzz
983e7683fd * i2psnark:
- Don't stay interested if we run out of pieces
        to request (thanks sponge)
      - Enhance debug mode to show requests
2010-10-27 13:29:27 +00:00
zzz
b9af4a8cf0 avoid rare transport NPE at startup 2010-10-27 13:25:13 +00:00
complication
f239d4f350 * Tiny readability fix: separate value and unit with a space. 2010-10-26 23:38:01 +00:00
z3d
4d77f62e38 I2PSnark: Fix alignment issue in file viewer filesize column. 2010-10-25 14:35:51 +00:00
zzz
ac3e6e27dc add note 2010-10-24 16:57:38 +00:00
zzz
4f9c442d55 fix disconnect race NPE 2010-10-24 16:56:43 +00:00
zzz
adab0cc3d3 * NTCP: Catch a race after stop() 2010-10-24 16:55:29 +00:00
zzz
b1f1725506 * Router: Set permissions on wrapper.log when not called by RouterLaunch 2010-10-24 16:52:41 +00:00
zzz
4bb902a8b9 * FileUtil: Make it easier to compile without Pack200, or with
Apache Harmony's Pack200, add unzip to main()
2010-10-24 16:49:20 +00:00
zzz
ed399a07d8 systray short doc and main() 2010-10-24 16:16:46 +00:00
z3d
4db38b9ba5 I2PSnark: Fix some showstopping whitespace issues. 2010-10-22 21:18:09 +00:00
z3d
22934545eb I2PSnark: Nuke the old copy of our snark theme in /themes/console/snark 2010-10-22 17:18:38 +00:00
z3d
7fe6b35359 I2PSnark: Tabs into spaces exercise. Release the kraken! 2010-10-22 16:49:07 +00:00
z3d
cfd2ad9a1c LICENSE.txt: Attribute I2PSnark's "Man with hat over face" graphic. 2010-10-22 16:33:30 +00:00
z3d
74a30aeee4 I2PSnark: Render unto Caesar what is due unto Caesar, namely some fixed tags. Enjoy! 2010-10-22 16:08:58 +00:00
z3d
1bff62e3c7 I2PSnark: Relocate theme to /themes/snark/ubergine/; update build.xml 2010-10-22 09:43:16 +00:00
z3d
31032cd794 merge of '42f7898ab54db310e16aa6fbedb1b078afe0ae18'
and '9d4166108eac930384ccb9c5859eede93f4d63ed'
2010-10-22 09:11:09 +00:00
z3d
8ccad29353 I2PSnark: Fix minor tag issue; add missing navbar bg graphic. 2010-10-22 09:01:29 +00:00
z3d
7ff873bbc9 merge of '6cf2d1b2af6daa4fffc59fede3407d3e10c09095'
and '9afc46edd20c72064eb24b5c1f6a4a8540e35799'
2010-10-22 08:25:44 +00:00
z3d
a55a464694 I2Psnark: Ensure our css uses the new path to our theme resources. 2010-10-22 08:17:49 +00:00
z3d
c14760c294 I2PSnark: Unbutcher tags; relocate our snark theme to /themes/snark; more css updates. 2010-10-22 08:14:51 +00:00
sponge
e6bf1af982 Sanity and some fixs for slackware package 2010-10-22 02:43:17 +00:00
sponge
3998ce311f Fix rc.i2p for slackware package 2010-10-22 02:26:13 +00:00
mathiasdm
e6c45ae5f8 Added package files for router. 2010-10-20 16:01:18 +00:00
mathiasdm
e8abe14395 Fixed susimail javadoc errors. 2010-10-20 15:55:28 +00:00
zzz
466128c179 * replaceAll() -> replace() when not using regex
* ampersand escaping (lots more to do)
2010-10-19 14:39:29 +00:00
zzz
8c7a39f00a * JobImpl: Deprecate getAddedBy() and addedToQueue()
to reduce LogManager records
2010-10-19 14:33:11 +00:00
echelon
1400c4d4d0 added plurals to fr, de and nl po file 2010-10-18 08:28:15 +00:00
zzz
24dd78394b priority persistence 2010-10-15 17:25:45 +00:00
zzz
9afff4f80a * i2psnark: Add file priority feature;
Use context random for shuffle; other cleanups
2010-10-15 13:48:36 +00:00
zzz
1aba324481 * I2PSocketEepGet: Set connect delay to save a RTT, will
speed announces in i2psnark
2010-10-15 13:41:56 +00:00
mathiasdm
3daa6b964d -Added package-file for time.
-Modified susi javadoc to remove more warnings (and non-javadoc '@see' to base class).
2010-10-14 16:05:06 +00:00
mathiasdm
8cda5104e3 - Added package doc for crypto and net.i2p
- Got rid of some susimail javadoc warnings
2010-10-14 06:19:19 +00:00
z3d
8db45ffaa1 merge of '01c6aeb6ee46c7795e83553f40e16b5bdae08aac'
and '56ee4b01df5de86f0fdc98cdc4ed1197104584b5'
2010-10-13 16:07:35 +00:00
z3d
b41e714a1b merge of '0738aeef8a1d4e9ca82dc5ba0077d83a57c47f81'
and '9625ea3e96d57df74bc62018bf64230a22c49ce0'
2010-10-13 16:07:33 +00:00
z3d
6cd645b34b I2PSnark: Tighten up navbar, color tweaks. 2010-10-13 16:03:41 +00:00
zzz
772c1d4fb8 explicit merge of '33c6e246dc934cddc886b50df2570c0caf122701'
and '4ef1d99f924ee431587d6f85241540e031fecbc1'
        to branch 'i2p.i2p'


Explicit merge from test4.
1.6 JDK now required to build.
1.5 JRE still OK to run I2P.

    * configlogging.jsp:
      - Add easy way to add an override
      - Make file size specifier more flexible
    * Console:
      - Sort RouterAddress options on netdb.jsp and peers.jsp
      - Remove unused web-*.xml file from war
    * Crypto:
      - Convert all ArrayList caching to LBQs in YKGenerator,
        HMACGenerator, and AESKeyCache.
      - Change DSAEngine params from Hash to new SHA1Hash, since
        these were really 20 byte hashes, not 32 byte Hashes.
      - Add stats to track YKGenerator caching success
      - Fix YKGenerator precalculation to be much more useful by
        increasing the cache size and dramatically shortening the delay
      - Option cleanups
      - YKGenerator cleanups
      - Mark HMAC256Generator unused
    * EepGet: Reset length variable on redirect
    * Files: Change permissions to 600/700 for all written files/directories.
      Now requires Java 1.6 to build, but only 1.5+ to run.
      (requires 1.6 to set permissiomns)
    * GeoIP: Fix locking bug causing lookups to stop
    * Hash: Throw IAE if data length is not 32 bytes,
      now that DSAEngine abuse is gone
    * HTTPResponseOutputStream:
      - More caching
      - Stats cleanup
      - Max header length check
      - Catch OOM
      - Initializer cleanup
      - Javadoc
    * I2CP:
      - Add new option i2cp.messageReliability=none, which prevents the
        router from sending MessageStatusMessages back in reply to an
        outbound SendMessageMessage. Since the streaming lib always ignored
        the MSMs anyway, make it the default for streaming.
        This will reduce the I2CP traffic significantly.
        MSM handling now avoided, but it is still fairly broken, see
        comments in I2PSessionImpl2.
      - Cleanups to replace method calls with fields
      - More cleanups, javadoc, rate reduction
    * i2psnark:
      - Compact response format
      - Add link to finished torrent in message box
      - Don't let one bad torrent prevent others from
        starting or stopping
      - Sort peers by completion %
      - Add some missing mime types to web.xml
      - shouldLog() cleanup
    * i2ptunnel:
      - Now that streaming flush() is fixed, use it in IRCClient, and
        for initial data in I2PTunnel runner, to avoid the 250 ms
        passive flush delay
      - Add hostname DSA signature field, to be used for addkey forms.
        Experimental, may be commented out later.
      - More header blocking (thanks telecomix!)
      - Remove unused web-*.xml file from war
    * Installer: Add startup hint for non-x86
    * Javadoc updates all over the place
    * LogConsoleBuffer: Java 5
    * Naming:
      - Increase cache size and expiration time
      - Add clearCache() method
      - Don't use EepGet or Exec for b32
      - Javadoc updates
    * NetDB:
      - Expire unreachable routers quickly, even if they don't have introducers,
        so we don't have old data on routers that ran out of introducers.
      - Fix rare NPEs at shutdown
    * NTCP:
      - Workaround for a rare 100% CPU bug in EventPumper
      - Cleanups
    * Streaming:
      - Make flush() block less, by waiting only for "accept" into the
        streaming queue rather than "completion" (i.e. ACK from the far end).
        This prevents complete stalls when flushing, and should help performance
        of apps that use flush(), like i2psnark (and SAM?).
        close() still does a flush that waits for completion, as i2ptunnel
        doesn't like a fast return from close().
      - cleanups
    * SusiDNS:
      - Remove unused web-*.xml file from war
    * TransportManager: Convert _transports from a List to a CHM
      to prevent a rare concurrent exception
    * Tunnels:
      - Don't use peers < 0.7.9 for tunnels due to the old
        message corruption bugs
      - Javadoc
      - Cleanups
    * UDP:
      - Beginnings of destroy message support
      - Try to avoid running out of introducers by relaxing selection criteria
        and increasing minimum number of potential introducers
      - Avoid rare AIOOBE
      - PacketBuilder refactor
      - Make most classes package private
      - Comments
      - Logging cleanup
      - Comment out a main()
2010-10-12 20:26:42 +00:00
HungryHobo
5a782cca4d Add HungryHobo as a signer 2010-10-12 19:30:46 +00:00
zzz
647b8f7fa1 default tweak 2010-10-11 15:18:17 +00:00
zzz
798bdf32c1 * Streaming:
- Make flush() block less, by waiting only for "accept" into the
        streaming queue rather than "completion" (i.e. ACK from the far end).
        This prevents complete window stalls when flushing, and should help performance
        of apps that use flush(), like i2psnark (and SAM?).
        close() still does a flush that waits for completion, as i2ptunnel
        doesn't like a fast return from close().
      - flush/close javadocs and comments
    * i2ptunnel:
      - Now that streaming flush() is fixed, use it in IRCClient, and
        for initial data in I2PTunnelRunner, to avoid the 250 ms
        passive flush delay
2010-10-11 15:17:35 +00:00
zzz
fbc20da606 more header blocking 2010-10-11 15:14:55 +00:00
sponge
0820b2c13f Bump version, add history 2010-10-10 14:36:11 +00:00
sponge
5f2361fe7c merge of '4ef1d99f924ee431587d6f85241540e031fecbc1'
and '56c6ae6a06651a05025a2e4f76ba35985a8ff372'
2010-10-10 14:32:35 +00:00
sponge
6e6142a91f Fulfill Request for name lookup feature. 2010-10-10 14:31:56 +00:00
zzz
500f6cf896 use context field 2010-10-07 18:42:30 +00:00
zzz
a23ea5e5f1 * configlogging.jsp:
- Add easy way to add an override
      - Make file size specifier more flexible
2010-10-07 18:39:03 +00:00
zzz
86a7d68f08 one more mime type 2010-10-07 15:14:07 +00:00
zzz
373fce2988 change perms on append too 2010-10-07 15:13:54 +00:00
zzz
8ac5d5d5fc add some missing mime types 2010-10-06 15:03:33 +00:00
zzz
3841e92d53 remove unused web-*.xml files from wars 2010-10-06 14:25:27 +00:00
walking
e5f53ed5e9 revise and fix 2010-10-06 13:07:34 +00:00
zzz
5ef9d46d0b dont sort in debug mode 2010-10-06 02:18:52 +00:00
zzz
5389ee056a sort snark peers by completion % 2010-10-06 02:05:26 +00:00
zzz
e2b7f93d11 fixup 2010-10-06 01:27:15 +00:00
zzz
09d1eb17d4 reset eepget length variable after a redirect 2010-10-06 01:11:21 +00:00
zzz
895c9a33a9 pluck build.xml javadoc changes from main branch 2010-10-05 14:52:44 +00:00
zzz
ab91d35331 comment 2010-10-05 13:15:39 +00:00
zzz
2d601099f3 propagate from branch 'i2p.i2p.zzz.test' (head 128a31611abc6a88e58133f3bf6a577fe6dd5b1c)
to branch 'i2p.i2p.zzz.test4' (head fa9a871892517271eb2531b433fe80a2a713be9c)
2010-10-05 13:06:16 +00:00
zzz
48ccf85e97 try again to fix the i2ptunnel nonce problem 2010-10-05 00:08:59 +00:00
zzz
6cf7bc7985 * i2ptunnel:
- Add hostname DSA signature field, to be used for addkey forms.
        Experimental, may be commented out later.
2010-10-02 17:20:39 +00:00
zzz
3d9b6061ce * NetDB:
- Expire unreachable routers quickly, even if they don't have introducers,
        so we don't have old data on routers that ran out of introducers.
      - Fix rare NPEs at shutdown
2010-10-02 17:07:37 +00:00
zzz
042cde2952 * UDP:
- Try to avoid running out of introducers by relaxing selection criteria
        and increasing minimum number of potential introducers
2010-10-02 17:04:52 +00:00
zzz
3b2aa946af * I2CP:
- Add new option i2cp.messageReliability=none, which prevents the
        router from sending MessageStatusMessages back in reply to an
        outbound SendMessageMessage. Since the streaming lib always ignored
        the MSMs anyway, make it the default for streaming.
        This will reduce the I2CP traffic significantly.
        MSM handling now avoided, but it is still fairly broken, see
        comments in I2PSessionImpl2.
      - Cleanups, javadoc, rate reduction
2010-10-02 16:56:02 +00:00
zzz
a687180d98 * TransportManager: Convert _transports from a List to a CHM
to prevent a rare concurrent exception
2010-10-02 16:30:07 +00:00
zzz
b1fd835f56 update irc description 2010-10-02 15:55:46 +00:00
zzz
53847dc3ad Sort RouterAddress options on peers.jsp and netdb.jsp 2010-10-02 15:51:48 +00:00
zzz
ec0c678cc9 * i2psnark:
- Add link to finished torrent in message box
      - Don't let one bad torrent prevent others from
        starting or stopping
2010-10-02 15:43:56 +00:00
zzz
b83184e895 initializer cleanup 2010-10-02 15:16:07 +00:00
zzz
f0f1a6f529 initializer cleanups, reduce rates, javadoc 2010-10-02 15:15:03 +00:00
zzz
333f80680e * UDP:
- Avoid rare AIOOBE
      - Comments
      - Logging cleanup
      - Comment out a main()
2010-10-02 15:11:41 +00:00
zzz
3489512a54 client cleanups 2010-10-02 15:07:35 +00:00
zzz
6100c799b7 LogConsoleBuffer cleanup 2010-10-02 15:03:20 +00:00
zzz
4a96e88118 * Hash: Throw IAE if data length is not 32 bytes,
now that DSAEngine abuse is gone
2010-10-02 15:00:30 +00:00
zzz
ed4c09b456 * Tunnels:
- Don't use peers < 0.7.9 for tunnels due to the old
        message corruption bugs
      - Javadoc
      - Cleanups
2010-10-02 14:56:45 +00:00
zzz
939dcee537 * GeoIP: Fix locking bug causing lookups to stop 2010-10-02 14:48:50 +00:00
zzz
7424fdd623 javadoc 2010-10-02 14:45:13 +00:00
zzz
4456048e79 * HTTPResponseOutputStream
- More caching
      - Stats cleanup
      - Max header length check
      - Catch OOM
      - Initializer cleanup
      - Javadoc
2010-10-02 14:43:40 +00:00
zzz
4c31c70298 Startup hint in installer for non-x86 2010-10-02 14:28:27 +00:00
zzz
c10a4f51ba I2CP: cleanups to replace method calls with fields 2010-10-02 14:27:01 +00:00
zzz
53dd0c7655 * Crypto:
- Convert all ArrayList caching to LBQs in YKGenerator,
        HMACGenerator, and AESKeyCache.
      - Change DSAEngine params from Hash to new SHA1Hash, since
        these were really 20 byte hashes, not 32 byte Hashes.
      - Add stats to track YKGenerator caching success
      - Fix YKGenerator precalculation to be much more useful by
        increasing the cache size and dramatically shortening the delay
      - Option cleanups
      - YKGenerator cleanups
      - Mark HMAC256Generator unused
2010-10-02 14:23:56 +00:00
zzz
6f449aa4f6 Naming:
- Increase cache size and expiration time
  - Add clearCache() method
  - Don't use EepGet or Exec for b32
  - Javadoc updates
2010-10-02 14:07:46 +00:00
zzz
171e3abe34 cleanups 2010-10-02 14:02:41 +00:00
zzz
2bffeea7eb comment out main 2010-10-02 14:01:38 +00:00
z3d
90288202e5 I2PSnark: Include missing add.png, spotted by xyz123. Bump to -3. 2010-10-02 00:36:31 +00:00
z3d
a4d24c61ba I2PSnark: Tweak the size of our writeable fields in add/create sections for better visual coherence. 2010-09-29 02:09:05 +00:00
z3d
3075593767 I2PSnark: Activity icons refresh. 2010-09-27 06:34:54 +00:00
z3d
8ab134ffe5 I2PSnark: Positional CSS tweaks 'n fiddles. 2010-09-27 06:05:02 +00:00
z3d
4800e73a4a I2PSnark: Add buttons for start/stop/delete torrents. 2010-09-27 05:04:05 +00:00
z3d
3bd97646a9 I2PSnark: Add favicon to file browser page; version bump to 0.8-02. 2010-09-23 04:56:43 +00:00
z3d
059e4176a1 I2PSnark: Rationalize file browser layout. 2010-09-23 02:43:05 +00:00
z3d
57b627fb71 I2PSnark: Add some icons to our file manager columns. 2010-09-22 21:18:57 +00:00
z3d
5281862932 I2PSnark: Kludge to fix extraneous space under message log on config page. 2010-09-20 21:07:27 +00:00
z3d
0fe2313754 I2PSnark: Configuration section tweaks. 2010-09-20 18:41:49 +00:00
z3d
f62dfb0abf I2PSnark: Invert show/hide peer icon functionality, tooltip change to "toggle peers"; fix alignment of "No torrents loaded" message with new css class; Replace brackets on Totals with &raquo;. 2010-09-20 11:26:28 +00:00
z3d
7507282886 I2PSnark: css tidyup. 2010-09-20 10:21:38 +00:00
z3d
9db5dd36b9 I2PSnark: alt tags, display filelength tweak. 2010-09-19 20:23:46 +00:00
z3d
9ce54d803f I2PSnark: show/hide peer icons. 2010-09-19 17:05:11 +00:00
z3d
7e7d36f0d6 I2PSnark: Table column header positional tweakery. 2010-09-19 15:43:57 +00:00
z3d
82323cd806 I2PSnark: Add icons for status and torrent columns. 2010-09-19 14:48:44 +00:00
z3d
511182f148 I2PSnark: status display tweakage. 2010-09-19 04:40:48 +00:00
z3d
e9b1db7ac7 I2PSnark: Update image references to point to our new snark theme directory. 2010-09-19 03:51:40 +00:00
z3d
9795334f12 build.xml: ensure we copy snark's directory, and remove the file copy for snark.css 2010-09-19 03:36:41 +00:00
z3d
321d88e795 I2PSnark: Add icons to relevant parts of the UI; rejigging of UI to minimise space wastage; create new snark directory in console/themes/ .. snark dir will need to be ignored when router scans directory for theme dirs. 2010-09-19 03:20:43 +00:00
z3d
99d2e2d0d0 I2PSnark: Fix alignment issue with snark_add.png 2010-09-18 16:36:29 +00:00
z3d
3fb1fbe1b3 I2PSnark: space savings! 2010-09-18 16:19:51 +00:00
z3d
d4f3304397 I2PSnark: Tweaks 'n fiddles. 2010-09-18 08:55:52 +00:00
z3d
4865373b4f I2PSnark: UI/theme tweaks. 2010-09-18 07:10:43 +00:00
z3d
5378b0ad56 I2PSnark: Transition from gray to puce. 2010-09-18 06:28:42 +00:00
z3d
7de357df98 Version bump. 2010-09-17 23:03:19 +00:00
z3d
27808012d0 I2PSnark: Reduced label lengths in preparation for icon substitution and tooltip; more colorification; Opera kludges. 2010-09-17 22:59:22 +00:00
z3d
dc22949b47 I2PSnark: more css polish; now with more color! 2010-09-17 16:02:15 +00:00
z3d
3d7ad215d9 I2PSnark: CSS Spit 'n polish. 2010-09-17 13:55:47 +00:00
z3d
67994d7e99 I2PSnark: snark.css fontsize tweaks. 2010-09-17 08:27:02 +00:00
z3d
deab6b40e0 I2PSnark: Fix text alignment issues. 2010-09-17 08:00:09 +00:00
z3d
0205fa6385 I2PSnark: snark.css finessing. 2010-09-17 07:27:21 +00:00
z3d
69b3343f45 Can't remember what. css stuff. 2010-09-16 23:33:24 +00:00
z3d
9c5b8419a5 I2PSnark: Add favicon. 2010-09-16 17:38:01 +00:00
z3d
fedf6d7537 I2PSnark css edits: log text visibility. 2010-09-16 16:49:27 +00:00
z3d
21306dbf5d merge of '1e79fc27bda464359d20795eaa33ed2ad61c9741'
and '7c6c62e901e75230e3a39e578f8fcbcf4cd2dd00'
2010-09-16 02:34:08 +00:00
z3d
9b69f2266a I2PSnark "faze to gray" theme: graphics and css futzing. 2010-09-16 02:32:07 +00:00
zzz
161f86b6bb improve and sort javadoc titles, put classes in the right places, add susi* 2010-09-15 15:25:32 +00:00
z3d
7f24dc5f03 Cross-browser tweaks to snark.css 2010-09-15 04:03:48 +00:00
z3d
6423c92b84 merge of '5e59656352811b3ccce9a2817417de1065ee9641'
and '8110890364bb45accd3016e90611f626e305b10e'
2010-09-15 01:50:30 +00:00
z3d
f7ea958961 Update history.txt to reflect Snark theme change. 2010-09-15 01:45:17 +00:00
z3d
8262048edc New default I2PSnark theme: faze to gray. 2010-09-15 01:39:38 +00:00
forget
73d956462f Fixed: recoded to UTF-8, cyrillic and chinese labels repaired. 2010-09-07 03:25:48 +00:00
forget
db0bc1a618 Fixed: missing links to the new Swedish help page. 2010-09-07 03:24:28 +00:00
zzz
91bcf947df * Javadocs
* Base64: comment out some unused methods
* Remove huge whitespace in CryptoConstants
* ElGamalAESEngine:
  - Reduce rates
  - Check number of tags earlier
2010-08-30 17:51:49 +00:00
z3d
c035ef6eb7 merge of '87f2562a0893b175a9b369e97b8413726f61935a'
and 'b1416986cd60fc129af81122324997fe0584472d'
2010-08-22 23:00:52 +00:00
z3d
4f31691c8a Add Swedish translation for eepsite help and update other help pages accordingly. Thanks to olleolleolle. 2010-08-20 22:51:58 +00:00
zzz
2244142bd8 javadoc, comment out some main()s 2010-08-14 18:22:46 +00:00
zzz
4323036992 javadocs 2010-08-10 16:17:09 +00:00
mathiasdm
8eeabe4409 merge of '85a542c53d910dffbf34cdcefb8a2faeee96adc4'
and 'c92f2bcd662936f16d539ea5e98b0d4496556384'
2010-08-08 10:01:51 +00:00
mathiasdm
6add722a25 Javadoc fix - thanks, duck! 2010-08-08 10:01:35 +00:00
mathiasdm
87abc1d6b4 CryptoConstants update from draft to RFC. 2010-07-31 12:49:38 +00:00
duck
6ddac9a478 Fix typo (trac #32) 2010-07-30 08:54:21 +00:00
echelon
38169b6d70 small fixes to _de 2010-07-26 12:08:17 +00:00
zzz
0634154b28 final compact response format 2010-07-11 14:45:12 +00:00
zzz
05ac2594b6 more shouldLog() 2010-07-09 17:40:59 +00:00
zzz
8353b623da SSU PacketBuilder: Refactor header generation, add destroy msg support 2010-07-09 16:34:54 +00:00
zzz
c19af4dbcf i2psnark:
- Rework PeerID class so it depends only on peer desthash, since
    peer ID is not available with compact format. Implement deferred
    lookup of destination.
  - Implement compact tracker requests and response handling
    (may not be the final format)
  - Fix Peer hashCode()
  - Java 5
2010-07-09 16:32:31 +00:00
zzz
01ef6baa53 beginnings of SSU destroy msg handling 2010-07-07 13:30:04 +00:00
zzz
a1524241cb Set permissions on directories and files when they are created 2010-07-06 15:22:48 +00:00
zzz
50bda941ad make most classes package local; stub out a session destroy message; javadoc 2010-07-05 16:03:13 +00:00
zzz
fc6306575d new classes, requires Java 1.6 to build 2010-07-05 16:01:50 +00:00
zzz
b9b737f4ce propagate from branch 'i2p.i2p' (head 08b1e0356e38567d4632bdc0269506b5d89f7a7c)
to branch 'i2p.i2p.zzz.test' (head 181daec1a6229c188282645875162287879cbbc6)
2010-06-30 22:29:33 +00:00
zzz
8ef1dac95b propagate from branch 'i2p.i2p' (head 45d9fab2e437a2acf99febfab1c50b28c342c694)
to branch 'i2p.i2p.zzz.test' (head 946c3527d4481d3dcf0b8ab163d1e248673c1733)
2010-06-05 10:32:27 +00:00
zzz
04efbc8819 propagate from branch 'i2p.i2p' (head 2c845f47f9323817088f27c61390558ad723b84a)
to branch 'i2p.i2p.zzz.test' (head 97a16a11a0fa27c0fa44df062573a51af938e068)
2010-04-14 14:05:39 +00:00
zzz
1fc288917a back to updater 2010-04-14 14:05:25 +00:00
705 changed files with 43887 additions and 17816 deletions

View File

@@ -68,6 +68,10 @@ Public domain except as listed below:
Copyright (C) 2001, 2007 Free Software Foundation, Inc.
See licenses/LICENSE-LGPLv2.1.txt
SSLEepGet:
Contains some code Copyright 2006 Sun Microsystems, Inc.
See licenses/LICENSE-InstallCert.txt
Router:
Public domain except as listed below:
@@ -236,3 +240,7 @@ distributions. See the source package for the additional license information.
SAM Python Library:
Public domain.
I2PSnark/Console themes:
"Man with hat over face" & related images licensed under a Creative Commons 2.0 license.
Original photos by Florian Kuhlmann. http://www.flickr.com/photos/floriankuhlmann/3117758155

View File

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

View File

@@ -2,27 +2,44 @@
# Start/stop i2p service.
i2p_start() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory start )"
# Check if router is up first!
/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..."
i2p_status
}
else
{
# 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 "/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
}
i2p_restart() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory restart)"
# We want a FULL cycle here, not the wrappers idea of this!
i2p_stop
i2p_start
}
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

@@ -85,23 +85,26 @@ cp -a ../i2p $PKG/$INSTALL_DIR/
mkdir -p $PKG/install
#############################################################################
# Preconfigureation to make package smaller
# Preconfigureation to make package smaller, and...
# we keep as much as reasonable in the installation directory.
# This makes the install map fairly well to the standard installation.
# It also makes it easier to find the log and pid files!
#############################################################################
cd $PKG/$INSTALL_DIR/i2p
# wrapper.config $INSTALL_PATH and $SYSTEM_java_io_tmpdir
sed "s|\$INSTALL_PATH|$INSTALL_DIR/i2p|g" wrapper.config > a
sed "s|\$SYSTEM_java_io_tmpdir|/var/tmp|g" a > wrapper.config
sed "s|\$INSTALL_PATH|/$INSTALL_DIR/i2p|g" wrapper.config > a
sed "s|\$SYSTEM_java_io_tmpdir|/$INSTALL_DIR/i2p|g" a > wrapper.config
# eepget %INSTALL_PATH
sed "s|\$INSTALL_PATH|$INSTALL_DIR/i2p|g" eepget > a
sed "s|\$INSTALL_PATH|/$INSTALL_DIR/i2p|g" eepget > a
rm eepget
mv a eepget
# runplain.sh %INSTALL_PATH and %SYSTEM_java_io_tmpdir
sed "s|%INSTALL_PATH|$INSTALL_DIR/i2p|g" runplain.sh > a
sed "s|%SYSTEM_java_io_tmpdir|/var/tmp|g" a > runplain.sh
sed "s|%INSTALL_PATH|/$INSTALL_DIR/i2p|g" runplain.sh > a
sed "s|%SYSTEM_java_io_tmpdir|/$INSTALL_DIR/i2p|g" a > runplain.sh
# i2prouter %INSTALL_PATH and %SYSTEM_java_io_tmpdir
sed "s|%INSTALL_PATH|$INSTALL_DIR/i2p|g" i2prouter > a
sed "s|%SYSTEM_java_io_tmpdir|/var/tmp|g" a > i2prouter
sed "s|%INSTALL_PATH|/$INSTALL_DIR/i2p|g" i2prouter > a
sed "s|%SYSTEM_java_io_tmpdir|/$INSTALL_DIR/i2p|g" a > i2prouter
chmod 744 ./i2prouter
chmod 744 ./osid

View File

@@ -34,7 +34,9 @@ import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PException;
import net.i2p.client.I2PClientFactory;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.util.Log;
// needed only for debugging.
// import java.util.logging.Level;
@@ -50,7 +52,7 @@ public class DoCMDS implements Runnable {
// FIX ME
// I need a better way to do versioning, but this will do for now.
public static final String BMAJ = "00", BMIN = "00", BREV = "0D", BEXT = "";
public static final String BMAJ = "00", BMIN = "00", BREV = "0E", BEXT = "";
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
private Socket server;
private Properties props;
@@ -86,6 +88,7 @@ public class DoCMDS implements Runnable {
private static final String C_inhost = "inhost";
private static final String C_inport = "inport";
private static final String C_list = "list";
private static final String C_lookup = "lookup";
private static final String C_newkeys = "newkeys";
private static final String C_option = "option";
private static final String C_outhost = "outhost";
@@ -113,6 +116,7 @@ public class DoCMDS implements Runnable {
{C_inhost, C_inhost + " hostname | IP * Set the inbound hostname or IP."},
{C_inport, C_inport + " port_number * Set the inbound port number nickname listens on."},
{C_list, C_list + " * List all tunnels."},
{C_lookup, C_lookup + " * Lookup an i2p address."},
{C_newkeys, C_newkeys + " * Generate a new keypair for the current nickname."},
{C_option, C_option + " I2CPoption=something * Set an I2CP option. NOTE: Don't use any spaces."},
{C_outhost, C_outhost + " hostname | IP * Set the outbound hostname or IP."},
@@ -138,6 +142,7 @@ public class DoCMDS implements Runnable {
C_inhost + " " +
C_inport + " " +
C_list + " " +
C_lookup + " " +
C_newkeys + " " +
C_option + " " +
C_outhost + " " +
@@ -446,6 +451,25 @@ public class DoCMDS implements Runnable {
} else if (Command.equals(C_visit)) {
visitAllThreads();
out.println("OK ");
} else if (Command.equals(C_lookup)) {
Destination dest = null;
String reply = null;
if (Arg.endsWith(".i2p")) {
try {
try {
dest = I2PTunnel.destFromName(Arg);
} catch (DataFormatException ex) {
}
reply = dest.toBase64();
} catch (NullPointerException npe) {
// Could not find the destination!?
}
}
if (reply == null) {
out.println("ERROR Address Not found.");
} else {
out.println("OK " + reply);
}
} else if (Command.equals(C_getdest)) {
if (ns) {
if (dk) {

View File

@@ -38,7 +38,7 @@ import net.i2p.util.EepGet;
* @author Ragnarok
*
*/
public class AddressBook {
class AddressBook {
private String location;
@@ -88,6 +88,8 @@ public class AddressBook {
* read or cannot be read, return an empty AddressBook.
* Set a maximum size of the remote book to make it a little harder for a malicious book-sender.
*
* Yes, the EepGet fetch() is done in this constructor.
*
* @param subscription
* A Subscription instance pointing at a remote address book.
* @param proxyHost hostname of proxy
@@ -102,6 +104,7 @@ public class AddressBook {
if (get.fetch()) {
subscription.setEtag(get.getETag());
subscription.setLastModified(get.getLastModified());
subscription.setLastFetched(I2PAppContext.getGlobalContext().clock().now());
}
try {
this.addresses = ConfigParser.parse(tmp);
@@ -196,6 +199,8 @@ public class AddressBook {
// null cert ends with AAAA but other zero-length certs would be AA
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AA")) ||
(dest.length() > MIN_DEST_LENGTH && dest.length() <= MAX_DEST_LENGTH)) &&
// B64 comes in groups of 2, 3, or 4 chars, but never 1
((dest.length() % 4) != 1) &&
dest.replaceAll("[a-zA-Z0-9~-]", "").length() == 0
;
}
@@ -253,6 +258,7 @@ public class AddressBook {
try {
ConfigParser.write(this.addresses, file);
} catch (IOException exp) {
System.err.println("Error writing addressbook " + file.getAbsolutePath() + " : " + exp.toString());
}
}
}

View File

@@ -25,9 +25,9 @@ import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Iterator;
@@ -35,6 +35,9 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import net.i2p.util.SecureFile;
import net.i2p.util.SecureFileOutputStream;
/**
* Utility class providing methods to parse and write files in config file
* format, and subscription file format.
@@ -44,7 +47,9 @@ import java.util.Map;
*
* @author Ragnarok
*/
public class ConfigParser {
class ConfigParser {
private static final boolean isWindows = System.getProperty("os.name").startsWith("Win");
/**
* Strip the comments from a String. Lines that begin with '#' and ';' are
@@ -140,7 +145,7 @@ public class ConfigParser {
* @param file
* A File to attempt to parse.
* @param map
* A Map to use as the default, if file fails.
* A Map containing values to use as defaults.
* @return A Map containing the key, value pairs from file, or if file
* cannot be read, map.
*/
@@ -148,6 +153,11 @@ public class ConfigParser {
Map result;
try {
result = ConfigParser.parse(file);
for (Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
String key = (String) iter.next();
if (!result.containsKey(key))
result.put(key, map.get(key));
}
} catch (IOException exp) {
result = map;
try {
@@ -267,7 +277,10 @@ public class ConfigParser {
/**
* Write contents of Map map to the File file. Output is written
* with one key, value pair on each line, in the format: key=value.
*
* Write to a temp file in the same directory and then rename, to not corrupt
* simultaneous accesses by the router. Except on Windows where renameTo()
* will fail if the target exists.
*
* @param map
* A Map to write to file.
* @param file
@@ -276,8 +289,22 @@ public class ConfigParser {
* if file cannot be written to.
*/
public static void write(Map map, File file) throws IOException {
ConfigParser
.write(map, new BufferedWriter(new FileWriter(file, false)));
boolean success = false;
if (!isWindows) {
File tmp = SecureFile.createTempFile("temp-", ".tmp", file.getAbsoluteFile().getParentFile());
ConfigParser
.write(map, new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(tmp), "UTF-8")));
success = tmp.renameTo(file);
if (!success) {
tmp.delete();
//System.out.println("Warning: addressbook rename fail from " + tmp + " to " + file);
}
}
if (!success) {
// hmm, that didn't work, try it the old way
ConfigParser
.write(map, new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(file), "UTF-8")));
}
}
/**
@@ -316,7 +343,7 @@ public class ConfigParser {
public static void writeSubscriptions(List list, File file)
throws IOException {
ConfigParser.writeSubscriptions(list, new BufferedWriter(
new FileWriter(file, false)));
new OutputStreamWriter(new SecureFileOutputStream(file), "UTF-8")));
}
}

View File

@@ -29,6 +29,7 @@ import java.util.List;
import java.util.Map;
import net.i2p.I2PAppContext;
import net.i2p.util.SecureDirectory;
/**
* Main class of addressbook. Performs updates, and runs the main loop.
@@ -37,7 +38,7 @@ import net.i2p.I2PAppContext;
*
*/
public class Daemon {
public static final String VERSION = "2.0.3";
public static final String VERSION = "2.0.4";
private static final Daemon _instance = new Daemon();
private boolean _running;
@@ -65,6 +66,7 @@ public class Daemon {
router.merge(master, true, null);
Iterator iter = subscriptions.iterator();
while (iter.hasNext()) {
// yes, the EepGet fetch() is done in next()
router.merge((AddressBook) iter.next(), false, log);
}
router.write();
@@ -96,6 +98,15 @@ public class Daemon {
File etagsFile = new File(home, (String) settings.get("etags"));
File lastModifiedFile = new File(home, (String) settings
.get("last_modified"));
File lastFetchedFile = new File(home, (String) settings
.get("last_fetched"));
long delay;
try {
delay = Long.parseLong((String) settings.get("update_delay"));
} catch (NumberFormatException nfe) {
delay = 12;
}
delay *= 60 * 60 * 1000;
AddressBook master = new AddressBook(masterFile);
AddressBook router = new AddressBook(routerFile);
@@ -105,7 +116,7 @@ public class Daemon {
defaultSubs.add("http://www.i2p2.i2p/hosts.txt");
SubscriptionList subscriptions = new SubscriptionList(subscriptionFile,
etagsFile, lastModifiedFile, defaultSubs, (String) settings
etagsFile, lastModifiedFile, lastFetchedFile, delay, defaultSubs, (String) settings
.get("proxy_host"), Integer.parseInt((String) settings.get("proxy_port")));
Log log = new Log(logFile);
@@ -131,11 +142,11 @@ public class Daemon {
String settingsLocation = "config.txt";
File homeFile;
if (args.length > 0) {
homeFile = new File(args[0]);
homeFile = new SecureDirectory(args[0]);
if (!homeFile.isAbsolute())
homeFile = new File(I2PAppContext.getGlobalContext().getRouterDir(), args[0]);
homeFile = new SecureDirectory(I2PAppContext.getGlobalContext().getRouterDir(), args[0]);
} else {
homeFile = new File(System.getProperty("user.dir"));
homeFile = new SecureDirectory(System.getProperty("user.dir"));
}
Map defaultSettings = new HashMap();
@@ -149,6 +160,7 @@ public class Daemon {
defaultSettings.put("subscriptions", "subscriptions.txt");
defaultSettings.put("etags", "etags");
defaultSettings.put("last_modified", "last_modified");
defaultSettings.put("last_fetched", "last_fetched");
defaultSettings.put("update_delay", "12");
if (!homeFile.exists()) {
@@ -164,7 +176,7 @@ public class Daemon {
Map settings = ConfigParser.parse(settingsFile, defaultSettings);
// wait
try {
Thread.sleep(5*60*1000);
Thread.sleep(5*60*1000 + I2PAppContext.getGlobalContext().random().nextLong(5*60*1000));
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
} catch (InterruptedException ie) {}

View File

@@ -27,7 +27,7 @@ package net.i2p.addressbook;
* @author Ragnarok
*
*/
public class DaemonThread extends Thread {
class DaemonThread extends Thread {
private String[] args;

View File

@@ -33,7 +33,7 @@ import java.util.Date;
* @author Ragnarok
*
*/
public class Log {
class Log {
private File file;

View File

@@ -27,13 +27,14 @@ package net.i2p.addressbook;
* @author Ragnarok
*
*/
public class Subscription {
class Subscription {
private String location;
private String etag;
private String lastModified;
private long lastFetched;
/**
* Construct a Subscription pointing to the address book at location, that
@@ -47,11 +48,17 @@ public class Subscription {
* @param lastModified
* the last-modified header we recieved the last time we read
* this subscription.
* @param lastFetched when the subscription was last fetched (Java time, as a String)
*/
public Subscription(String location, String etag, String lastModified) {
public Subscription(String location, String etag, String lastModified, String lastFetched) {
this.location = location;
this.etag = etag;
this.lastModified = lastModified;
if (lastFetched != null) {
try {
this.lastFetched = Long.parseLong(lastFetched);
} catch (NumberFormatException nfe) {}
}
}
/**
@@ -102,4 +109,14 @@ public class Subscription {
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
}
/** @since 0.8.2 */
public long getLastFetched() {
return this.lastFetched;
}
/** @since 0.8.2 */
public void setLastFetched(long t) {
this.lastFetched = t;
}
}

View File

@@ -21,31 +21,39 @@
package net.i2p.addressbook;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper; // debug
/**
* An iterator over the subscriptions in a SubscriptionList. Note that this iterator
* returns AddressBook objects, and not Subscription objects.
* Yes, the EepGet fetch() is done in here in next().
*
* @author Ragnarok
*/
public class SubscriptionIterator implements Iterator {
class SubscriptionIterator implements Iterator {
private Iterator subIterator;
private String proxyHost;
private int proxyPort;
private final long delay;
/**
* Construct a SubscriptionIterator using the Subscriprions in List subscriptions.
*
* @param subscriptions
* List of Subscription objects that represent address books.
* @param delay the minimum delay since last fetched for the iterator to actually fetch
* @param proxyHost proxy hostname
* @param proxyPort proxt port number
*/
public SubscriptionIterator(List subscriptions, String proxyHost, int proxyPort) {
public SubscriptionIterator(List subscriptions, long delay, String proxyHost, int proxyPort) {
this.subIterator = subscriptions.iterator();
this.delay = delay;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
}
@@ -58,12 +66,24 @@ public class SubscriptionIterator implements Iterator {
return this.subIterator.hasNext();
}
/* (non-Javadoc)
* @see java.util.Iterator#next()
/**
* Yes, the EepGet fetch() is done in here in next().
*
* see java.util.Iterator#next()
* @return an AddressBook (empty if the minimum delay has not been met)
*/
public Object next() {
Subscription sub = (Subscription) this.subIterator.next();
return new AddressBook(sub, this.proxyHost, this.proxyPort);
if (sub.getLastFetched() + this.delay < I2PAppContext.getGlobalContext().clock().now()) {
//System.err.println("Fetching addressbook from " + sub.getLocation());
return new AddressBook(sub, this.proxyHost, this.proxyPort);
} else {
//System.err.println("Addressbook " + sub.getLocation() + " was last fetched " +
// DataHelper.formatDuration(I2PAppContext.getGlobalContext().clock().now() - sub.getLastFetched()) +
// " ago but the minimum delay is " +
// DataHelper.formatDuration(this.delay));
return new AddressBook(Collections.EMPTY_MAP);
}
}
/* (non-Javadoc)
@@ -72,4 +92,4 @@ public class SubscriptionIterator implements Iterator {
public void remove() {
throw new UnsupportedOperationException();
}
}
}

View File

@@ -35,13 +35,15 @@ import java.util.Map;
* @author Ragnarok
*
*/
public class SubscriptionList {
class SubscriptionList {
private List subscriptions;
private File etagsFile;
private File lastModifiedFile;
private File lastFetchedFile;
private final long delay;
private String proxyHost;
@@ -60,20 +62,24 @@ public class SubscriptionList {
* @param lastModifiedFile
* A file containg the last-modified headers used for conditional
* GET. The file is in the format "url=leastmodified".
* @param delay the minimum delay since last fetched for the iterator to actually fetch
* @param defaultSubs default subscription file
* @param proxyHost proxy hostname
* @param proxyPort proxy port number
*/
public SubscriptionList(File locationsFile, File etagsFile,
File lastModifiedFile, List defaultSubs, String proxyHost,
File lastModifiedFile, File lastFetchedFile, long delay, List defaultSubs, String proxyHost,
int proxyPort) {
this.subscriptions = new LinkedList();
this.etagsFile = etagsFile;
this.lastModifiedFile = lastModifiedFile;
this.lastFetchedFile = lastFetchedFile;
this.delay = delay;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
Map etags;
Map lastModified;
Map lastFetched;
String location;
List locations = ConfigParser.parseSubscriptions(locationsFile,
defaultSubs);
@@ -87,11 +93,17 @@ public class SubscriptionList {
} catch (IOException exp) {
lastModified = new HashMap();
}
try {
lastFetched = ConfigParser.parse(lastFetchedFile);
} catch (IOException exp) {
lastFetched = new HashMap();
}
Iterator iter = locations.iterator();
while (iter.hasNext()) {
location = (String) iter.next();
this.subscriptions.add(new Subscription(location, (String) etags
.get(location), (String) lastModified.get(location)));
this.subscriptions.add(new Subscription(location, (String) etags.get(location),
(String) lastModified.get(location),
(String) lastFetched.get(location)));
}
}
@@ -102,18 +114,22 @@ public class SubscriptionList {
* @return A SubscriptionIterator.
*/
public SubscriptionIterator iterator() {
return new SubscriptionIterator(this.subscriptions, this.proxyHost,
return new SubscriptionIterator(this.subscriptions, this.delay, this.proxyHost,
this.proxyPort);
}
/**
* Write the etag and last-modified headers for each Subscription to files.
* Write the etag and last-modified headers,
* and the last-fetched time, for each Subscription to files.
* BUG - If the subscription URL is a cgi containing an '=' the files
* won't be read back correctly; the '=' should be escaped.
*/
public void write() {
Iterator iter = this.subscriptions.iterator();
Subscription sub;
Map etags = new HashMap();
Map lastModified = new HashMap();
Map lastFetched = new HashMap();
while (iter.hasNext()) {
sub = (Subscription) iter.next();
if (sub.getEtag() != null) {
@@ -122,11 +138,13 @@ public class SubscriptionList {
if (sub.getLastModified() != null) {
lastModified.put(sub.getLocation(), sub.getLastModified());
}
lastFetched.put(sub.getLocation(), "" + sub.getLastFetched());
}
try {
ConfigParser.write(etags, this.etagsFile);
ConfigParser.write(lastModified, this.lastModifiedFile);
ConfigParser.write(lastFetched, this.lastFetchedFile);
} catch (IOException exp) {
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

View File

@@ -3,9 +3,7 @@
<target name="all" depends="clean, build" />
<target name="build" depends="builddep, jar, war" />
<target name="builddep">
<ant dir="../../jetty/" target="build" />
<ant dir="../../streaming/java/" target="build" />
<!-- streaming will build ministreaming and core -->
<!-- run from top level build.xml to get dependencies built -->
</target>
<condition property="depend.available">
<typefound name="depend" />

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

@@ -0,0 +1,14 @@
package org.klomp.snark;
/**
* Callback used to fetch data
* @since 0.8.2
*/
interface DataLoader
{
/**
* This is the callback that PeerConnectionOut calls to get the data from disk
* @return bytes or null for errors
*/
public byte[] loadData(int piece, int begin, int length);
}

View File

@@ -0,0 +1,36 @@
package org.klomp.snark;
import java.util.HashMap;
import java.util.Map;
import org.klomp.snark.bencode.BEncoder;
import org.klomp.snark.bencode.BEValue;
/**
* REF: BEP 10 Extension Protocol
* @since 0.8.2
*/
class ExtensionHandshake {
private static final byte[] _payload = buildPayload();
/**
* @return bencoded data
*/
static byte[] getPayload() {
return _payload;
}
/** just a test for now */
private static byte[] buildPayload() {
Map<String, Object> handshake = new HashMap();
Map<String, Integer> m = new HashMap();
m.put("foo", Integer.valueOf(99));
m.put("bar", Integer.valueOf(101));
handshake.put("m", m);
handshake.put("p", Integer.valueOf(6881));
handshake.put("v", "I2PSnark");
handshake.put("reqq", Integer.valueOf(5));
return BEncoder.bencode(handshake);
}
}

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;
@@ -26,6 +28,8 @@ import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.EepGet;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFile;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.Translate;
@@ -77,7 +81,7 @@ public class I2PSnarkUtil {
// This is used for both announce replies and .torrent file downloads,
// so it must be available even if not connected to I2CP.
// so much for multiple instances
_tmpDir = new File(ctx.getTempDir(), "i2psnark");
_tmpDir = new SecureDirectory(ctx.getTempDir(), "i2psnark");
FileUtil.rmdir(_tmpDir, false);
_tmpDir.mkdirs();
}
@@ -151,6 +155,9 @@ public class I2PSnarkUtil {
*/
synchronized public boolean connect() {
if (_manager == null) {
// try to find why reconnecting after stop
if (_log.shouldLog(Log.DEBUG))
_log.debug("Connecting to I2P", new Exception("I did it"));
Properties opts = new Properties();
if (_opts != null) {
for (Iterator iter = _opts.keySet().iterator(); iter.hasNext(); ) {
@@ -162,6 +169,10 @@ public class I2PSnarkUtil {
opts.setProperty("inbound.nickname", "I2PSnark");
if (opts.getProperty("outbound.nickname") == null)
opts.setProperty("outbound.nickname", "I2PSnark");
// Dont do this for now, it is set in I2PSocketEepGet for announces,
// we don't need fast handshake for peer connections.
//if (opts.getProperty("i2p.streaming.connectDelay") == null)
// opts.setProperty("i2p.streaming.connectDelay", "500");
if (opts.getProperty("i2p.streaming.inactivityTimeout") == null)
opts.setProperty("i2p.streaming.inactivityTimeout", "240000");
if (opts.getProperty("i2p.streaming.inactivityAction") == null)
@@ -185,6 +196,7 @@ public class I2PSnarkUtil {
*/
public void disconnect() {
I2PSocketManager mgr = _manager;
// FIXME this can cause race NPEs elsewhere
_manager = null;
_shitlist.clear();
mgr.destroySocketManager();
@@ -196,11 +208,17 @@ public class I2PSnarkUtil {
/** connect to the given destination */
I2PSocket connect(PeerID peer) throws IOException {
Hash dest = peer.getAddress().calculateHash();
I2PSocketManager mgr = _manager;
if (mgr == null)
throw new IOException("No socket manager");
Destination addr = peer.getAddress();
if (addr == null)
throw new IOException("Null address");
Hash dest = addr.calculateHash();
if (_shitlist.contains(dest))
throw new IOException("Not trying to contact " + dest.toBase64() + ", as they are shitlisted");
try {
I2PSocket rv = _manager.connect(peer.getAddress());
I2PSocket rv = _manager.connect(addr);
if (rv != null)
_shitlist.remove(dest);
return rv;
@@ -224,11 +242,12 @@ public class I2PSnarkUtil {
public File get(String url, boolean rewrite) { return get(url, rewrite, 0); }
public File get(String url, int retries) { return get(url, true, retries); }
public File get(String url, boolean rewrite, int retries) {
_log.debug("Fetching [" + url + "] proxy=" + _proxyHost + ":" + _proxyPort + ": " + _shouldProxy);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Fetching [" + url + "] proxy=" + _proxyHost + ":" + _proxyPort + ": " + _shouldProxy);
File out = null;
try {
// we could use the system tmp dir but deleteOnExit() doesn't seem to work on all platforms...
out = File.createTempFile("i2psnark", null, _tmpDir);
out = SecureFile.createTempFile("i2psnark", null, _tmpDir);
} catch (IOException ioe) {
ioe.printStackTrace();
if (out != null)
@@ -248,10 +267,12 @@ public class I2PSnarkUtil {
}
EepGet get = new I2PSocketEepGet(_context, _manager, retries, out.getAbsolutePath(), fetchURL);
if (get.fetch()) {
_log.debug("Fetch successful [" + url + "]: size=" + out.length());
if (_log.shouldLog(Log.DEBUG))
_log.debug("Fetch successful [" + url + "]: size=" + out.length());
return out;
} else {
_log.warn("Fetch failed [" + url + "]");
if (_log.shouldLog(Log.WARN))
_log.warn("Fetch failed [" + url + "]");
out.delete();
return null;
}
@@ -297,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,23 +39,34 @@ class Message
final static byte REQUEST = 6;
final static byte PIECE = 7;
final static byte CANCEL = 8;
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
byte type;
// Used for HAVE, REQUEST, PIECE and CANCEL messages.
// low byte used for EXTENSION message
int piece;
// Used for REQUEST, PIECE and CANCEL messages.
int begin;
int length;
// Used for PIECE and BITFIELD messages
// Used for PIECE and BITFIELD and EXTENSION messages
byte[] data;
int off;
int len;
// Used to do deferred fetch of data
DataLoader dataLoader;
SimpleTimer.TimedEvent expireEvent;
/** Utility method for sending a message through a DataStream. */
@@ -68,6 +79,13 @@ class Message
return;
}
// Get deferred data
if (data == null && dataLoader != null) {
data = dataLoader.loadData(piece, begin, length);
if (data == null)
return; // hmm will get retried, but shouldn't happen
}
// Calculate the total length in bytes
// Type is one byte.
@@ -85,8 +103,12 @@ class Message
if (type == REQUEST || type == CANCEL)
datalen += 4;
// length is 1 byte
if (type == EXTENSION)
datalen += 1;
// add length of data for piece or bitfield array.
if (type == BITFIELD || type == PIECE)
if (type == BITFIELD || type == PIECE || type == EXTENSION)
datalen += len;
// Send length
@@ -105,8 +127,11 @@ class Message
if (type == REQUEST || type == CANCEL)
dos.writeInt(length);
if (type == EXTENSION)
dos.writeByte((byte) piece & 0xff);
// Send actual data
if (type == BITFIELD || type == PIECE)
if (type == BITFIELD || type == PIECE || type == EXTENSION)
dos.write(data, off, len);
}
@@ -135,6 +160,8 @@ class Message
return "PIECE(" + piece + "," + begin + "," + length + ")";
case CANCEL:
return "CANCEL(" + piece + "," + begin + "," + length + ")";
case EXTENSION:
return "EXTENSION(" + piece + ',' + data.length + ')';
default:
return "<UNKNOWN>";
}

View File

@@ -109,7 +109,8 @@ public class MetaInfo
*/
public MetaInfo(Map m) throws InvalidBEncodingException
{
_log.debug("Creating a metaInfo: " + m, new Exception("source"));
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating a metaInfo: " + m, new Exception("source"));
BEValue val = (BEValue)m.get("announce");
if (val == null)
throw new InvalidBEncodingException("Missing announce string");
@@ -290,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);
}
@@ -446,14 +447,16 @@ public class MetaInfo
else
buf.append(val.toString());
}
_log.debug(buf.toString());
if (_log.shouldLog(Log.DEBUG))
_log.debug(buf.toString());
byte[] infoBytes = BEncoder.bencode(info);
//_log.debug("info bencoded: [" + Base64.encode(infoBytes, true) + "]");
try
{
MessageDigest digest = MessageDigest.getInstance("SHA");
byte hash[] = digest.digest(infoBytes);
_log.debug("info hash: [" + net.i2p.data.Base64.encode(hash) + "]");
if (_log.shouldLog(Log.DEBUG))
_log.debug("info hash: [" + net.i2p.data.Base64.encode(hash) + "]");
return hash;
}
catch(NoSuchAlgorithmException nsa)

View File

@@ -0,0 +1,104 @@
package org.klomp.snark;
/**
* This is the class passed from PeerCoordinator to PeerState so
* PeerState may start requests.
*
* It is also passed from PeerState to PeerCoordinator when
* a piece is not completely downloaded, for example
* when the Peer disconnects or chokes.
*
* @since 0.8.2
*/
class PartialPiece implements Comparable {
private final int piece;
private final byte[] bs;
private final int off;
private final long createdTime;
/**
* Used by PeerCoordinator.
* Creates a new PartialPiece, with no chunks yet downloaded.
* Allocates the data.
*
* @param piece Piece number requested.
* @param len must be equal to the piece length
*/
public PartialPiece (int piece, int len) throws OutOfMemoryError {
this.piece = piece;
this.bs = new byte[len];
this.off = 0;
this.createdTime = 0;
}
/**
* Used by PeerState.
* Creates a new PartialPiece, with chunks up to but not including
* firstOutstandingRequest already downloaded and stored in the Request byte array.
*
* Note that this cannot handle gaps; chunks after a missing chunk cannot be saved.
* That would be harder.
*
* @param firstOutstandingRequest the first request not fulfilled for the piece
*/
public PartialPiece (Request firstOutstandingRequest) {
this.piece = firstOutstandingRequest.piece;
this.bs = firstOutstandingRequest.bs;
this.off = firstOutstandingRequest.off;
this.createdTime = System.currentTimeMillis();
}
/**
* Convert this PartialPiece to a request for the next chunk.
* Used by PeerState only.
*/
public Request getRequest() {
return new Request(this.piece, this.bs, this.off, Math.min(this.bs.length - this.off, PeerState.PARTSIZE));
}
/** piece number */
public int getPiece() {
return this.piece;
}
/** how many bytes are good */
public int getDownloaded() {
return this.off;
}
public long getCreated() {
return this.createdTime;
}
/**
* Highest downloaded first
*/
public int compareTo(Object o) throws ClassCastException {
return ((PartialPiece)o).off - this.off; // reverse
}
@Override
public int hashCode() {
return piece * 7777;
}
/**
* Make this simple so PeerCoordinator can keep a List.
* Warning - compares piece number only!
*/
@Override
public boolean equals(Object o) {
if (o instanceof PartialPiece) {
PartialPiece pp = (PartialPiece)o;
return pp.piece == this.piece;
}
return false;
}
@Override
public String toString() {
return "Partial(" + piece + ',' + off + ',' + bs.length + ')';
}
}

View File

@@ -27,6 +27,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.util.Log;
@@ -56,10 +57,17 @@ public class Peer implements Comparable
private long _id;
final static long CHECK_PERIOD = PeerCoordinator.CHECK_PERIOD; // 40 seconds
final static int RATE_DEPTH = PeerCoordinator.RATE_DEPTH; // make following arrays RATE_DEPTH long
private long uploaded_old[] = {-1,-1,-1,-1,-1,-1};
private long downloaded_old[] = {-1,-1,-1,-1,-1,-1};
private long uploaded_old[] = {-1,-1,-1};
private long downloaded_old[] = {-1,-1,-1};
// 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;
/**
* Outgoing connection.
* Creates a disconnected peer given a PeerID, your own id and the
* relevant MetaInfo.
*/
@@ -70,10 +78,11 @@ 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"));
}
/**
* Incoming connection.
* Creates a unconnected peer from the input and output stream got
* from the socket. Note that the complete handshake (which can take
* some time or block indefinitely) is done in the calling Thread to
@@ -92,7 +101,8 @@ public class Peer implements Comparable
byte[] id = handshake(in, out);
this.peerID = new PeerID(id, sock.getPeerDestination());
_id = ++__id;
_log.debug("Creating a new peer with " + peerID.getAddress().calculateHash().toBase64(), new Exception("creating " + _id));
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating a new peer with " + peerID.toString(), new Exception("creating " + _id));
}
/**
@@ -116,10 +126,15 @@ public class Peer implements Comparable
}
/**
* Returns socket (for debug printing)
* @return socket debug string (for debug printing)
*/
public String getSocket()
{
if (state != null) {
String r = state.getRequests();
if (r != null)
return sock.toString() + "<br>Requests: " + r;
}
return sock.toString();
}
@@ -129,7 +144,7 @@ public class Peer implements Comparable
@Override
public int hashCode()
{
return peerID.hashCode() ^ (2 << _id);
return peerID.hashCode() ^ (7777 * (int)_id);
}
/**
@@ -150,6 +165,7 @@ public class Peer implements Comparable
/**
* Compares the PeerIDs.
* @deprecated unused?
*/
public int compareTo(Object o)
{
@@ -181,14 +197,17 @@ public class Peer implements Comparable
if (state != null)
throw new IllegalStateException("Peer already started");
_log.debug("Running connection to " + peerID.getAddress().calculateHash().toBase64(), new Exception("connecting"));
if (_log.shouldLog(Log.DEBUG))
_log.debug("Running connection to " + peerID.toString(), new Exception("connecting"));
try
{
// Do we need to handshake?
if (din == null)
{
// Outgoing connection
sock = util.connect(peerID);
_log.debug("Connected to " + peerID + ": " + sock);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Connected to " + peerID + ": " + sock);
if ((sock == null) || (sock.isClosed())) {
throw new IOException("Unable to reach " + peerID);
}
@@ -207,20 +226,33 @@ public class Peer implements Comparable
// = new BufferedOutputStream(sock.getOutputStream());
byte [] id = handshake(in, out); //handshake(bis, bos);
byte [] expected_id = peerID.getID();
if (!Arrays.equals(expected_id, id))
throw new IOException("Unexpected peerID '"
if (expected_id == null) {
peerID.setID(id);
} else if (Arrays.equals(expected_id, id)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Handshake got matching IDs with " + toString());
} else {
throw new IOException("Unexpected peerID '"
+ PeerID.idencode(id)
+ "' expected '"
+ PeerID.idencode(expected_id) + "'");
_log.debug("Handshake got matching IDs with " + toString());
}
} else {
_log.debug("Already have din [" + sock + "] with " + toString());
// Incoming connection
if (_log.shouldLog(Log.DEBUG))
_log.debug("Already have din [" + sock + "] with " + toString());
}
PeerConnectionIn in = new PeerConnectionIn(this, din);
PeerConnectionOut out = new PeerConnectionOut(this, dout);
PeerState s = new PeerState(this, listener, metainfo, in, out);
if ((options & OPTION_EXTENSION) != 0) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Peer supports extensions, sending test message");
out.sendExtension(0, ExtensionHandshake.getPayload());
}
// Send our bitmap
if (bitfield != null)
s.out.sendBitfield(bitfield);
@@ -229,7 +261,8 @@ public class Peer implements Comparable
state = s;
listener.connected(this);
_log.debug("Start running the reader with " + toString());
if (_log.shouldLog(Log.DEBUG))
_log.debug("Start running the reader with " + toString());
// Use this thread for running the incomming connection.
// The outgoing connection creates its own Thread.
out.startup();
@@ -269,9 +302,8 @@ public class Peer implements Comparable
// Handshake write - header
dout.write(19);
dout.write("BitTorrent protocol".getBytes("UTF-8"));
// Handshake write - zeros
byte[] zeros = new byte[8];
dout.write(zeros);
// Handshake write - options
dout.writeLong(OPTION_EXTENSION);
// Handshake write - metainfo hash
byte[] shared_hash = metainfo.getInfoHash();
dout.write(shared_hash);
@@ -279,7 +311,8 @@ public class Peer implements Comparable
dout.write(my_id);
dout.flush();
_log.debug("Wrote my shared hash and ID to " + toString());
if (_log.shouldLog(Log.DEBUG))
_log.debug("Wrote my shared hash and ID to " + toString());
// Handshake read - header
byte b = din.readByte();
@@ -295,8 +328,8 @@ public class Peer implements Comparable
+ "'Bittorrent protocol', got '"
+ bittorrentProtocol + "'");
// Handshake read - zeros
din.readFully(zeros);
// Handshake read - options
options = din.readLong();
// Handshake read - metainfo hash
bs = new byte[20];
@@ -306,7 +339,15 @@ public class Peer implements Comparable
// Handshake read - peer id
din.readFully(bs);
_log.debug("Read the remote side's hash and peerID fully from " + toString());
if (_log.shouldLog(Log.DEBUG))
_log.debug("Read the remote side's hash and peerID fully from " + toString());
if (options != 0) {
// send them something
if (_log.shouldLog(Log.DEBUG))
_log.debug("Peer supports options 0x" + Long.toString(options, 16) + ": " + toString());
}
return bs;
}
@@ -337,8 +378,11 @@ public class Peer implements Comparable
if (this.deregister) {
PeerListener p = s.listener;
if (p != null) {
p.savePeerPartial(s);
p.markUnrequested(this);
List<PartialPiece> pcs = s.returnPartialPieces();
if (!pcs.isEmpty())
p.savePartialPieces(this, pcs);
// now covered by savePartialPieces
//p.markUnrequested(this);
}
}
state = null;
@@ -374,6 +418,38 @@ public class Peer implements Comparable
s.havePiece(piece);
}
/**
* Tell the other side that we are no longer interested in any of
* the outstanding requests (if any) for this piece.
* @since 0.8.1
*/
void cancel(int piece) {
PeerState s = state;
if (s != null)
s.cancelPiece(piece);
}
/**
* Are we currently requesting the piece?
* @deprecated deadlocks
* @since 0.8.1
*/
boolean isRequesting(int p) {
PeerState s = state;
return s != null && s.isRequesting(p);
}
/**
* Update the request queue.
* Call after adding wanted pieces.
* @since 0.8.1
*/
void request() {
PeerState s = state;
if (s != null)
s.addRequest();
}
/**
* Whether or not the peer is interested in pieces we have. Returns
* false if not connected.
@@ -532,17 +608,8 @@ public class Peer implements Comparable
*/
public void setRateHistory(long up, long down)
{
setRate(up, uploaded_old);
setRate(down, downloaded_old);
}
private void setRate(long val, long array[])
{
synchronized(array) {
for (int i = RATE_DEPTH-1; i > 0; i--)
array[i] = array[i-1];
array[0] = val;
}
PeerCoordinator.setRate(up, uploaded_old);
PeerCoordinator.setRate(down, downloaded_old);
}
/**
@@ -550,28 +617,11 @@ public class Peer implements Comparable
*/
public long getUploadRate()
{
return getRate(uploaded_old);
return PeerCoordinator.getRate(uploaded_old);
}
public long getDownloadRate()
{
return getRate(downloaded_old);
return PeerCoordinator.getRate(downloaded_old);
}
private long getRate(long array[])
{
long rate = 0;
int i = 0;
synchronized(array) {
for ( ; i < RATE_DEPTH; i++){
if (array[i] < 0)
break;
rate += array[i];
}
}
if (i == 0)
return 0;
return rate / (i * CHECK_PERIOD / 1000);
}
}

View File

@@ -76,10 +76,12 @@ public class PeerAcceptor
// is this working right?
try {
peerInfoHash = readHash(in);
_log.info("infohash read from " + socket.getPeerDestination().calculateHash().toBase64()
+ ": " + Base64.encode(peerInfoHash));
if (_log.shouldLog(Log.INFO))
_log.info("infohash read from " + socket.getPeerDestination().calculateHash().toBase64()
+ ": " + Base64.encode(peerInfoHash));
} catch (IOException ioe) {
_log.info("Unable to read the infohash from " + socket.getPeerDestination().calculateHash().toBase64());
if (_log.shouldLog(Log.INFO))
_log.info("Unable to read the infohash from " + socket.getPeerDestination().calculateHash().toBase64());
throw ioe;
}
in = new SequenceInputStream(new ByteArrayInputStream(peerInfoHash), in);

View File

@@ -49,10 +49,8 @@ class PeerCheckerTask extends TimerTask
public void run()
{
synchronized(coordinator.peers)
{
Iterator it = coordinator.peers.iterator();
if ((!it.hasNext()) || coordinator.halted()) {
List<Peer> peerList = coordinator.peerList();
if (peerList.isEmpty() || coordinator.halted()) {
coordinator.peerCount = 0;
coordinator.interestedAndChoking = 0;
coordinator.setRateHistory(0, 0);
@@ -76,19 +74,18 @@ class PeerCheckerTask extends TimerTask
// Keep track of peers we remove now,
// we will add them back to the end of the list.
List removed = new ArrayList();
List<Peer> removed = new ArrayList();
int uploadLimit = coordinator.allowedUploaders();
boolean overBWLimit = coordinator.overUpBWLimit();
while (it.hasNext())
{
Peer peer = (Peer)it.next();
for (Peer peer : peerList) {
// Remove dying peers
if (!peer.isConnected())
{
it.remove();
coordinator.removePeerFromPieces(peer);
coordinator.peerCount = coordinator.peers.size();
// This was just a failsafe, right?
//it.remove();
//coordinator.removePeerFromPieces(peer);
//coordinator.peerCount = coordinator.peers.size();
continue;
}
@@ -117,8 +114,9 @@ class PeerCheckerTask extends TimerTask
// Choke a percentage of them rather than all so it isn't so drastic...
// unless this torrent is over the limit all by itself.
// choke 5/8 of the time when seeding and 3/8 when leeching
boolean overBWLimitChoke = upload > 0 &&
((overBWLimit && random.nextBoolean()) ||
((overBWLimit && (random.nextInt(8) > (coordinator.completed() ? 2 : 4))) ||
(coordinator.overUpBWLimit(uploaded)));
// If we are at our max uploaders and we have lots of other
@@ -140,7 +138,6 @@ class PeerCheckerTask extends TimerTask
coordinator.uploaders--;
// Put it at the back of the list
it.remove();
removed.add(peer);
}
else if (overBWLimitChoke)
@@ -153,7 +150,6 @@ class PeerCheckerTask extends TimerTask
removedCount++;
// Put it at the back of the list for fairness, even though we won't be unchoking this time
it.remove();
removed.add(peer);
}
else if (peer.isInteresting() && peer.isChoked())
@@ -166,7 +162,6 @@ class PeerCheckerTask extends TimerTask
removedCount++;
// Put it at the back of the list
it.remove();
removed.add(peer);
}
else if (!peer.isInteresting() && !coordinator.completed())
@@ -179,7 +174,6 @@ class PeerCheckerTask extends TimerTask
removedCount++;
// Put it at the back of the list
it.remove();
removed.add(peer);
}
else if (peer.isInteresting()
@@ -195,7 +189,6 @@ class PeerCheckerTask extends TimerTask
removedCount++;
// Put it at the back of the list
it.remove();
removed.add(peer);
}
else if (peer.isInteresting() && !peer.isChoked() &&
@@ -234,8 +227,6 @@ class PeerCheckerTask extends TimerTask
removedCount++;
// Put it at the back of the list
coordinator.peers.remove(worstDownloader);
coordinator.peerCount = coordinator.peers.size();
removed.add(worstDownloader);
}
@@ -244,8 +235,12 @@ class PeerCheckerTask extends TimerTask
coordinator.unchokePeer();
// Put peers back at the end of the list that we removed earlier.
coordinator.peers.addAll(removed);
coordinator.peerCount = coordinator.peers.size();
synchronized (coordinator.peers) {
for(Peer peer : removed) {
if (coordinator.peers.remove(peer))
coordinator.peers.add(peer);
}
}
coordinator.interestedAndChoking += removedCount;
// store the rates
@@ -255,6 +250,5 @@ class PeerCheckerTask extends TimerTask
if (random.nextInt(4) == 0)
coordinator.getStorage().cleanRAFs();
}
}
}

View File

@@ -171,6 +171,14 @@ class PeerConnectionIn implements Runnable
if (_log.shouldLog(Log.DEBUG))
_log.debug("Received cancel(" + piece + "," + begin + ") from " + peer + " on " + peer.metainfo.getName());
break;
case 20: // Extension message
int id = din.readUnsignedByte();
byte[] payload = new byte[i-2];
din.readFully(payload);
ps.extensionMessage(id, payload);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Received extension message from " + peer + " on " + peer.metainfo.getName());
break;
default:
byte[] bs = new byte[i-1];
din.readFully(bs);

View File

@@ -42,7 +42,7 @@ class PeerConnectionOut implements Runnable
private boolean quit;
// Contains Messages.
private final List sendQueue = new ArrayList();
private final List<Message> sendQueue = new ArrayList();
private static long __id = 0;
private long _id;
@@ -229,12 +229,9 @@ class PeerConnectionOut implements Runnable
/**
* Adds a message to the sendQueue and notifies the method waiting
* on the sendQueue to change.
* If a PIECE message only, add a timeout.
*/
private void addMessage(Message m)
{
if (m.type == Message.PIECE)
SimpleScheduler.getInstance().addEvent(new RemoveTooSlow(m), SEND_TIMEOUT);
synchronized(sendQueue)
{
sendQueue.add(m);
@@ -430,6 +427,42 @@ class PeerConnectionOut implements Runnable
return total;
}
/**
* Queue a piece message with a callback to load the data
* from disk when required.
* @since 0.8.2
*/
void sendPiece(int piece, int begin, int length, DataLoader loader)
{
boolean sendNow = false;
// are there any cases where we should?
if (sendNow) {
// queue the real thing
byte[] bytes = loader.loadData(piece, begin, length);
if (bytes != null)
sendPiece(piece, begin, length, bytes);
return;
}
// queue a fake message... set everything up,
// except save the PeerState instead of the bytes.
Message m = new Message();
m.type = Message.PIECE;
m.piece = piece;
m.begin = begin;
m.length = length;
m.dataLoader = loader;
m.off = 0;
m.len = length;
addMessage(m);
}
/**
* Queue a piece message with the data already loaded from disk
* Also add a timeout.
* We don't use this anymore.
*/
void sendPiece(int piece, int begin, int length, byte[] bytes)
{
Message m = new Message();
@@ -440,6 +473,8 @@ class PeerConnectionOut implements Runnable
m.data = bytes;
m.off = 0;
m.len = length;
// since we have the data already loaded, queue a timeout to remove it
SimpleScheduler.getInstance().addEvent(new RemoveTooSlow(m), SEND_TIMEOUT);
addMessage(m);
}
@@ -469,6 +504,19 @@ class PeerConnectionOut implements Runnable
addMessage(m);
}
/**
* Remove all Request messages from the queue
* @since 0.8.2
*/
void cancelRequestMessages() {
synchronized(sendQueue) {
for (Iterator<Message> it = sendQueue.iterator(); it.hasNext(); ) {
if (it.next().type == Message.REQUEST)
it.remove();
}
}
}
// Called by the PeerState when the other side doesn't want this
// request to be handled anymore. Removes any pending Piece Message
// from out send queue.
@@ -488,4 +536,15 @@ class PeerConnectionOut implements Runnable
}
}
}
/** @since 0.8.2 */
void sendExtension(int id, byte[] bytes) {
Message m = new Message();
m.type = Message.EXTENSION;
m.piece = id;
m.data = bytes;
m.off = 0;
m.len = bytes.length;
addMessage(m);
}
}

View File

@@ -22,16 +22,19 @@ package org.klomp.snark;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Random;
import java.util.Timer;
import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.I2PAppContext;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
/**
* Coordinates what peer does what.
@@ -57,27 +60,34 @@ public class PeerCoordinator implements PeerListener
private long uploaded;
private long downloaded;
final static int RATE_DEPTH = 6; // make following arrays RATE_DEPTH long
private long uploaded_old[] = {-1,-1,-1,-1,-1,-1};
private long downloaded_old[] = {-1,-1,-1,-1,-1,-1};
final static int RATE_DEPTH = 3; // make following arrays RATE_DEPTH long
private long uploaded_old[] = {-1,-1,-1};
private long downloaded_old[] = {-1,-1,-1};
// synchronize on this when changing peers or downloaders
final List<Peer> peers = new ArrayList();
// This is a Queue, not a Set, because PeerCheckerTask keeps things in order for choking/unchoking
final Queue<Peer> peers;
/** estimate of the peers, without requiring any synchronization */
volatile int peerCount;
/** Timer to handle all periodical tasks. */
private final Timer timer = new Timer(true);
private final CheckEvent timer;
private final byte[] id;
// Some random wanted pieces
private List<Piece> wantedPieces;
/** The wanted pieces. We could use a TreeSet but we'd have to clear and re-add everything
* when priorities change.
*/
private final List<Piece> wantedPieces;
/** partial pieces - lock by synching on wantedPieces */
private final List<PartialPiece> partialPieces;
private boolean halted = false;
private final CoordinatorListener listener;
public I2PSnarkUtil _util;
private static final Random _random = I2PAppContext.getGlobalContext().random();
public String trackerProblems = null;
public int trackerSeenPeers = 0;
@@ -92,25 +102,54 @@ public class PeerCoordinator implements PeerListener
this.listener = listener;
this.snark = torrent;
wantedPieces = new ArrayList();
setWantedPieces();
partialPieces = new ArrayList(getMaxConnections() + 1);
peers = new LinkedBlockingQueue();
// Install a timer to check the uploaders.
// Randomize the first start time so multiple tasks are spread out,
// this will help the behavior with global limits
Random r = I2PAppContext.getGlobalContext().random();
timer.schedule(new PeerCheckerTask(_util, this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
timer = new CheckEvent(new PeerCheckerTask(_util, this));
timer.schedule((CHECK_PERIOD / 2) + _random.nextInt((int) CHECK_PERIOD));
}
/**
* Run the PeerCheckerTask via the SimpleTimer2 executors
* @since 0.8.2
*/
private static class CheckEvent extends SimpleTimer2.TimedEvent {
private final PeerCheckerTask _task;
public CheckEvent(PeerCheckerTask task) {
super(SimpleTimer2.getInstance());
_task = task;
}
public void timeReached() {
_task.run();
schedule(CHECK_PERIOD);
}
}
// only called externally from Storage after the double-check fails
public void setWantedPieces()
{
// Make a list of pieces
wantedPieces = new ArrayList();
BitField bitfield = storage.getBitField();
for(int i = 0; i < metainfo.getPieces(); i++)
if (!bitfield.get(i))
wantedPieces.add(new Piece(i));
Collections.shuffle(wantedPieces);
synchronized(wantedPieces) {
wantedPieces.clear();
BitField bitfield = storage.getBitField();
int[] pri = storage.getPiecePriorities();
for (int i = 0; i < metainfo.getPieces(); i++) {
// only add if we don't have and the priority is >= 0
if ((!bitfield.get(i)) &&
(pri == null || pri[i] >= 0)) {
Piece p = new Piece(i);
if (pri != null)
p.setPriority(pri[i]);
wantedPieces.add(p);
}
}
Collections.shuffle(wantedPieces, _random);
}
}
public Storage getStorage() { return storage; }
@@ -119,10 +158,7 @@ public class PeerCoordinator implements PeerListener
// for web page detailed stats
public List<Peer> peerList()
{
synchronized(peers)
{
return new ArrayList(peers);
}
}
public byte[] getID()
@@ -141,12 +177,9 @@ public class PeerCoordinator implements PeerListener
/** should be right */
public int getPeers()
{
synchronized(peers)
{
int rv = peers.size();
peerCount = rv;
return rv;
}
}
/**
@@ -183,7 +216,7 @@ public class PeerCoordinator implements PeerListener
setRate(down, downloaded_old);
}
private static void setRate(long val, long array[])
static void setRate(long val, long array[])
{
synchronized(array) {
for (int i = RATE_DEPTH-1; i > 0; i--)
@@ -214,20 +247,23 @@ public class PeerCoordinator implements PeerListener
return (r * 1000) / CHECK_PERIOD;
}
private long getRate(long array[])
static long getRate(long array[])
{
long rate = 0;
int i = 0;
int factor = 0;
synchronized(array) {
for ( ; i < RATE_DEPTH; i++) {
if (array[i] < 0)
break;
rate += array[i];
int f = RATE_DEPTH - i;
rate += array[i] * f;
factor += f;
}
}
if (i == 0)
return 0;
return rate / (i * CHECK_PERIOD / 1000);
return rate / (factor * CHECK_PERIOD / 1000);
}
public MetaInfo getMetaInfo()
@@ -237,10 +273,7 @@ public class PeerCoordinator implements PeerListener
public boolean needPeers()
{
synchronized(peers)
{
return !halted && peers.size() < getMaxConnections();
}
}
/**
@@ -280,7 +313,9 @@ public class PeerCoordinator implements PeerListener
removePeerFromPieces(peer);
}
// delete any saved orphan partial piece
savedRequest = null;
synchronized (partialPieces) {
partialPieces.clear();
}
}
public void connected(Peer peer)
@@ -325,7 +360,10 @@ public class PeerCoordinator implements PeerListener
// Add it to the beginning of the list.
// And try to optimistically make it a uploader.
peers.add(0, peer);
// Can't add to beginning since we converted from a List to a Queue
// We can do this in Java 6 with a Deque
//peers.add(0, peer);
peers.add(peer);
peerCount = peers.size();
unchokePeer();
@@ -339,8 +377,10 @@ public class PeerCoordinator implements PeerListener
}
}
// caller must synchronize on peers
private static Peer peerIDInList(PeerID pid, List peers)
/**
* @return peer if peer id is in the collection, else null
*/
private static Peer peerIDInList(PeerID pid, Collection<Peer> peers)
{
Iterator<Peer> it = peers.iterator();
while (it.hasNext()) {
@@ -375,7 +415,8 @@ public class PeerCoordinator implements PeerListener
if (need_more)
{
_log.debug("Adding a peer " + peer.getPeerID().getAddress().calculateHash().toBase64() + " for " + metainfo.getName(), new Exception("add/run"));
if (_log.shouldLog(Log.DEBUG))
_log.debug("Adding a peer " + peer.getPeerID().toString() + " for " + metainfo.getName(), new Exception("add/run"));
// Run the peer with us as listener and the current bitfield.
final PeerListener listener = this;
@@ -387,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;
}
@@ -409,7 +450,6 @@ public class PeerCoordinator implements PeerListener
// At the start are the peers that have us unchoked at the end the
// other peer that are interested, but are choking us.
List<Peer> interested = new LinkedList();
synchronized (peers) {
int count = 0;
int unchokedCount = 0;
int maxUploaders = allowedUploaders();
@@ -444,7 +484,6 @@ public class PeerCoordinator implements PeerListener
peerCount = peers.size();
}
interestedAndChoking = count;
}
}
public byte[] getBitMap()
@@ -453,7 +492,7 @@ public class PeerCoordinator implements PeerListener
}
/**
* Returns true if we don't have the given piece yet.
* @return true if we still want the given piece
*/
public boolean gotHave(Peer peer, int piece)
{
@@ -498,27 +537,49 @@ public class PeerCoordinator implements PeerListener
*/
private static final int END_GAME_THRESHOLD = 8;
/**
* Max number of peers to get a piece from when in end game
* @since 0.8.1
*/
private static final int MAX_PARALLEL_REQUESTS = 4;
/**
* Returns one of pieces in the given BitField that is still wanted or
* -1 if none of the given pieces are wanted.
*/
public int wantPiece(Peer peer, BitField havePieces)
{
public int wantPiece(Peer peer, BitField havePieces) {
return wantPiece(peer, havePieces, true);
}
/**
* Returns one of pieces in the given BitField that is still wanted or
* -1 if none of the given pieces are wanted.
*
* @param record if true, actually record in our data structures that we gave the
* request to this peer. If false, do not update the data structures.
* @since 0.8.2
*/
private int wantPiece(Peer peer, BitField havePieces, boolean record) {
if (halted) {
if (_log.shouldLog(Log.WARN))
_log.warn("We don't want anything from the peer, as we are halted! peer=" + peer);
return -1;
}
Piece piece = null;
List<Piece> requested = new ArrayList();
int wantedSize = END_GAME_THRESHOLD + 1;
synchronized(wantedPieces)
{
Piece piece = null;
Collections.sort(wantedPieces); // Sort in order of rarest first.
List<Piece> requested = new ArrayList();
if (record)
Collections.sort(wantedPieces); // Sort in order of rarest first.
Iterator<Piece> it = wantedPieces.iterator();
while (piece == null && it.hasNext())
{
Piece p = it.next();
// sorted by priority, so when we hit a disabled piece we are done
if (p.isDisabled())
break;
if (havePieces.get(p.getId()) && !p.isRequested())
{
piece = p;
@@ -528,24 +589,33 @@ public class PeerCoordinator implements PeerListener
requested.add(p);
}
}
if (piece == null)
wantedSize = wantedPieces.size();
//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).
// If we do end game all the time, we generate lots of extra traffic
// when the seeder is super-slow and all the peers are "caught up"
if (wantedPieces.size() > END_GAME_THRESHOLD)
if (wantedSize > END_GAME_THRESHOLD)
return -1; // nothing to request and not in end game
// let's not all get on the same piece
Collections.shuffle(requested);
// Even better would be to sort by number of requests
if (record)
Collections.shuffle(requested, _random);
Iterator<Piece> it2 = requested.iterator();
while (piece == null && it2.hasNext())
{
Piece p = it2.next();
if (havePieces.get(p.getId()))
{
piece = p;
}
if (havePieces.get(p.getId())) {
// limit number of parallel requests
int requestedCount = p.getRequestCount();
if (requestedCount < MAX_PARALLEL_REQUESTS &&
!p.isRequestedBy(peer)) {
piece = p;
break;
}
}
}
if (piece == null) {
if (_log.shouldLog(Log.WARN))
@@ -554,16 +624,84 @@ public class PeerCoordinator implements PeerListener
// + " wanted = " + wantedPieces + " peerHas = " + havePieces);
return -1; //If we still can't find a piece we want, so be it.
} else {
// Should be a lot smarter here - limit # of parallel attempts and
// Should be a lot smarter here -
// share blocks rather than starting from 0 with each peer.
// This is where the flaws of the snark data model are really exposed.
// Could also randomize within the duplicate set rather than strict rarest-first
if (_log.shouldLog(Log.DEBUG))
_log.debug("parallel request (end game?) for " + peer + ": piece = " + piece);
if (_log.shouldLog(Log.INFO))
_log.info("parallel request (end game?) for " + peer + ": piece = " + piece);
}
}
piece.setRequested(true);
if (record) {
if (_log.shouldLog(Log.INFO))
_log.info(peer + " is now requesting: piece " + piece + " priority " + piece.getPriority());
piece.setRequested(peer, true);
}
return piece.getId();
} // synch
}
/**
* Maps file priorities to piece priorities.
* Call after updating file priorities Storage.setPriority()
* @since 0.8.1
*/
public void updatePiecePriorities() {
int[] pri = storage.getPiecePriorities();
if (pri == null) {
_log.debug("Updated piece priorities called but no priorities to set?");
return;
}
synchronized(wantedPieces) {
// Add incomplete and previously unwanted pieces to the list
// Temp to avoid O(n**2)
BitField want = new BitField(pri.length);
for (Piece p : wantedPieces) {
want.set(p.getId());
}
BitField bitfield = storage.getBitField();
for (int i = 0; i < pri.length; i++) {
if (pri[i] >= 0 && !bitfield.get(i)) {
if (!want.get(i)) {
Piece piece = new Piece(i);
wantedPieces.add(piece);
// As connections are already up, new Pieces will
// not have their PeerID list populated, so do that.
for (Peer p : peers) {
PeerState s = p.state;
if (s != null) {
BitField bf = s.bitfield;
if (bf != null && bf.get(i))
piece.addPeer(p);
}
}
}
}
}
// now set the new priorities and remove newly unwanted pieces
for (Iterator<Piece> iter = wantedPieces.iterator(); iter.hasNext(); ) {
Piece p = iter.next();
int priority = pri[p.getId()];
if (priority >= 0) {
p.setPriority(priority);
} else {
iter.remove();
// cancel all peers
for (Peer peer : peers) {
peer.cancel(p.getId());
}
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Updated piece priorities, now wanted: " + wantedPieces);
// if we added pieces, they will be in-order unless we shuffle
Collections.shuffle(wantedPieces, _random);
// update request queues, in case we added wanted pieces
// and we were previously uninterested
for (Peer peer : peers) {
peer.request();
}
}
}
@@ -631,14 +769,18 @@ public class PeerCoordinator implements PeerListener
// No need to announce have piece to peers.
// Assume we got a good piece, we don't really care anymore.
return true;
// Well, this could be caused by a change in priorities, so
// only return true if we already have it, otherwise might as well keep it.
if (storage.getBitField().get(piece))
return true;
}
try
{
if (storage.putPiece(piece, bs))
{
_log.info("Got valid piece " + piece + "/" + metainfo.getPieces() +" from " + peer + " for " + metainfo.getName());
if (_log.shouldLog(Log.INFO))
_log.info("Got valid piece " + piece + "/" + metainfo.getPieces() +" from " + peer + " for " + metainfo.getName());
}
else
{
@@ -657,10 +799,11 @@ public class PeerCoordinator implements PeerListener
wantedPieces.remove(p);
}
// just in case
removePartialPiece(piece);
// Announce to the world we have it!
// Disconnect from other seeders when we get the last piece
synchronized(peers)
{
List<Peer> toDisconnect = new ArrayList();
Iterator<Peer> it = peers.iterator();
while (it.hasNext())
@@ -680,11 +823,11 @@ public class PeerCoordinator implements PeerListener
Peer p = it.next();
p.disconnect(true);
}
}
return true;
}
/** this does nothing but logging */
public void gotChoke(Peer peer, boolean choke)
{
if (_log.shouldLog(Log.INFO))
@@ -698,8 +841,6 @@ public class PeerCoordinator implements PeerListener
{
if (interest)
{
synchronized(peers)
{
if (uploaders < allowedUploaders())
{
if(peer.isChoking())
@@ -710,7 +851,6 @@ public class PeerCoordinator implements PeerListener
_log.info("Unchoke: " + peer);
}
}
}
}
if (listener != null)
@@ -750,127 +890,173 @@ public class PeerCoordinator implements PeerListener
}
}
/** Simple method to save a partial piece on peer disconnection
/**
* Save partial pieces on peer disconnection
* and hopefully restart it later.
* Only one partial piece is saved at a time.
* Replace it if a new one is bigger or the old one is too old.
* Replace a partial piece in the List if the new one is bigger.
* Storage method is private so we can expand to save multiple partials
* if we wish.
*
* Also mark the piece unrequested if this peer was the only one.
*
* @param peer partials, must include the zero-offset (empty) ones too
* @since 0.8.2
*/
private Request savedRequest = null;
private long savedRequestTime = 0;
public void savePeerPartial(PeerState state)
public void savePartialPieces(Peer peer, List<PartialPiece> partials)
{
if (halted)
return;
Request req = state.getPartialRequest();
if (req == null)
return;
if (savedRequest == null ||
req.off > savedRequest.off ||
System.currentTimeMillis() > savedRequestTime + (15 * 60 * 1000)) {
if (savedRequest == null || (req.piece != savedRequest.piece && req.off != savedRequest.off)) {
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(" Saving orphaned partial piece " + req);
if (savedRequest != null)
_log.debug(" (Discarding previously saved orphan) " + savedRequest);
}
}
savedRequest = req;
savedRequestTime = System.currentTimeMillis();
} else {
if (req.piece != savedRequest.piece)
if (_log.shouldLog(Log.DEBUG))
_log.debug(" Discarding orphaned partial piece " + req);
}
}
/** Return partial piece if it's still wanted and peer has it.
*/
public Request getPeerPartial(BitField havePieces) {
if (savedRequest == null)
return null;
if (! havePieces.get(savedRequest.piece)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Peer doesn't have orphaned piece " + savedRequest);
return null;
}
synchronized(wantedPieces)
{
for(Iterator<Piece> iter = wantedPieces.iterator(); iter.hasNext(); ) {
Piece piece = iter.next();
if (piece.getId() == savedRequest.piece) {
Request req = savedRequest;
piece.setRequested(true);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Restoring orphaned partial piece " + req);
savedRequest = null;
return req;
if (halted)
return;
if (_log.shouldLog(Log.INFO))
_log.info("Partials received from " + peer + ": " + partials);
synchronized(wantedPieces) {
for (PartialPiece pp : partials) {
if (pp.getDownloaded() > 0) {
// PartialPiece.equals() only compares piece number, which is what we want
int idx = partialPieces.indexOf(pp);
if (idx < 0) {
partialPieces.add(pp);
if (_log.shouldLog(Log.INFO))
_log.info("Saving orphaned partial piece (new) " + pp);
} else if (idx >= 0 && pp.getDownloaded() > partialPieces.get(idx).getDownloaded()) {
// replace what's there now
partialPieces.set(idx, pp);
if (_log.shouldLog(Log.INFO))
_log.info("Saving orphaned partial piece (bigger) " + pp);
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Discarding partial piece (not bigger)" + pp);
}
int max = getMaxConnections();
if (partialPieces.size() > max) {
// sorts by remaining bytes, least first
Collections.sort(partialPieces);
PartialPiece gone = partialPieces.remove(max);
if (_log.shouldLog(Log.INFO))
_log.info("Discarding orphaned partial piece (list full)" + gone);
}
} // else drop the empty partial piece
// synchs on wantedPieces...
markUnrequested(peer, pp.getPiece());
}
}
if (_log.shouldLog(Log.INFO))
_log.info("Partial list size now: " + partialPieces.size());
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("We no longer want orphaned piece " + savedRequest);
savedRequest = null;
return null;
}
/** Clear the requested flag for a piece if the peer
** is the only one requesting it
/**
* Return partial piece to the PeerState if it's still wanted and peer has it.
* @param havePieces pieces the peer has, the rv will be one of these
*
* @return PartialPiece or null
* @since 0.8.2
*/
private void markUnrequestedIfOnlyOne(Peer peer, int piece)
{
// see if anybody else is requesting
synchronized (peers)
{
Iterator<Peer> it = peers.iterator();
while (it.hasNext()) {
Peer p = it.next();
if (p.equals(peer))
continue;
if (p.state == null)
continue;
int[] arr = p.state.getRequestedPieces();
for (int i = 0; arr[i] >= 0; i++)
if(arr[i] == piece) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Another peer is requesting piece " + piece);
return;
}
}
public PartialPiece getPartialPiece(Peer peer, BitField havePieces) {
synchronized(wantedPieces) {
// sorts by remaining bytes, least first
Collections.sort(partialPieces);
for (Iterator<PartialPiece> iter = partialPieces.iterator(); iter.hasNext(); ) {
PartialPiece pp = iter.next();
int savedPiece = pp.getPiece();
if (havePieces.get(savedPiece)) {
iter.remove();
// this is just a double-check, it should be in there
for(Piece piece : wantedPieces) {
if (piece.getId() == savedPiece) {
piece.setRequested(peer, true);
if (_log.shouldLog(Log.INFO)) {
_log.info("Restoring orphaned partial piece " + pp +
" Partial list size now: " + partialPieces.size());
}
return pp;
}
}
if (_log.shouldLog(Log.WARN))
_log.warn("Partial piece " + pp + " NOT in wantedPieces??");
}
}
if (_log.shouldLog(Log.WARN) && !partialPieces.isEmpty())
_log.warn("Peer " + peer + " has none of our partials " + partialPieces);
}
// ...and this section turns this into the general move-requests-around code!
// Temporary? So PeerState never calls wantPiece() directly for now...
int piece = wantPiece(peer, havePieces);
if (piece >= 0) {
try {
return new PartialPiece(piece, metainfo.getPieceLength(piece));
} catch (OutOfMemoryError oom) {
if (_log.shouldLog(Log.WARN))
_log.warn("OOM creating new partial piece");
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("We have no partial piece to return");
return null;
}
// nobody is, so mark unrequested
/**
* Called when we are downloading from the peer and may need to ask for
* a new piece. Returns true if wantPiece() or getPartialPiece() would return a piece.
*
* @param peer the Peer that will be asked to provide the piece.
* @param havePieces a BitField containing the pieces that the other
* side has.
*
* @return if we want any of what the peer has
* @since 0.8.2
*/
public boolean needPiece(Peer peer, BitField havePieces) {
synchronized(wantedPieces) {
for (PartialPiece pp : partialPieces) {
int savedPiece = pp.getPiece();
if (havePieces.get(savedPiece)) {
// this is just a double-check, it should be in there
for(Piece piece : wantedPieces) {
if (piece.getId() == savedPiece) {
if (_log.shouldLog(Log.INFO)) {
_log.info("We could restore orphaned partial piece " + pp);
}
return true;
}
}
}
}
}
return wantPiece(peer, havePieces, false) >= 0;
}
/**
* Remove saved state for this piece.
* Unless we are in the end game there shouldnt be anything in there.
* Do not call with wantedPieces lock held (deadlock)
*/
private void removePartialPiece(int piece) {
synchronized(wantedPieces) {
for (Iterator<PartialPiece> iter = partialPieces.iterator(); iter.hasNext(); ) {
PartialPiece pp = iter.next();
if (pp.getPiece() == piece) {
iter.remove();
// there should be only one but keep going to be sure
}
}
}
}
/**
* Clear the requested flag for a piece
*/
private void markUnrequested(Peer peer, int piece)
{
synchronized(wantedPieces)
{
Iterator<Piece> it = wantedPieces.iterator();
while (it.hasNext()) {
Piece p = it.next();
if (p.getId() == piece) {
p.setRequested(false);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Removing from request list piece " + piece);
for (Piece pc : wantedPieces) {
if (pc.getId() == piece) {
pc.setRequested(peer, false);
return;
}
}
}
}
/** Mark a peer's requested pieces unrequested when it is disconnected
** Once for each piece
** This is enough trouble, maybe would be easier just to regenerate
** the requested list from scratch instead.
*/
public void markUnrequested(Peer peer)
{
if (halted || peer.state == null)
return;
int[] arr = peer.state.getRequestedPieces();
for (int i = 0; arr[i] >= 0; i++)
markUnrequestedIfOnlyOne(peer, arr[i]);
}
/** Return number of allowed uploaders for this torrent.
** Check with Snark to see if we are over the total upload limit.
*/

View File

@@ -24,19 +24,33 @@ import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Map;
import net.i2p.I2PAppContext;
import net.i2p.data.Base32;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import org.klomp.snark.bencode.BDecoder;
import org.klomp.snark.bencode.BEValue;
import org.klomp.snark.bencode.InvalidBEncodingException;
/**
* Store the address information about a peer.
* Prior to 0.8.1, an instantiation required a peer ID, and full Destination address.
* Starting with 0.8.1, to support compact tracker responses,
* a PeerID can be instantiated with a Destination Hash alone.
* The full destination lookup is deferred until getAddress() is called,
* and the PeerID is not required.
* Equality is now determined solely by the dest hash.
*/
public class PeerID implements Comparable
{
private final byte[] id;
private final Destination address;
private byte[] id;
private Destination address;
private final int port;
private byte[] destHash;
/** whether we have tried to get the dest from the hash - only do once */
private boolean triedDestLookup;
private final int hash;
public PeerID(byte[] id, Destination address)
@@ -44,7 +58,7 @@ public class PeerID implements Comparable
this.id = id;
this.address = address;
this.port = 6881;
this.destHash = address.calculateHash().getData();
hash = calculateHash();
}
@@ -77,17 +91,49 @@ public class PeerID implements Comparable
throw new InvalidBEncodingException("Invalid destination [" + bevalue.getString() + "]");
port = 6881;
this.destHash = address.calculateHash().getData();
hash = calculateHash();
}
/**
* Creates a PeerID from a destHash
* @since 0.8.1
*/
public PeerID(byte[] dest_hash) throws InvalidBEncodingException
{
// id and address remain null
port = 6881;
if (dest_hash.length != 32)
throw new InvalidBEncodingException("bad hash length");
destHash = dest_hash;
hash = DataHelper.hashCode(dest_hash);
}
public byte[] getID()
{
return id;
}
public Destination getAddress()
/** for connecting out to peer based on desthash @since 0.8.1 */
public void setID(byte[] xid)
{
id = xid;
}
/**
* Get the destination.
* If this PeerId was instantiated with a destHash,
* and we have not yet done so, lookup the full destination, which may take
* up to 10 seconds.
* @return Dest or null if unknown
*/
public synchronized Destination getAddress()
{
if (address == null && destHash != null && !triedDestLookup) {
String b32 = Base32.encode(destHash) + ".b32.i2p";
address = I2PAppContext.getGlobalContext().namingService().lookup(b32);
triedDestLookup = true;
}
return address;
}
@@ -96,16 +142,19 @@ public class PeerID implements Comparable
return port;
}
/** @since 0.8.1 */
public byte[] getDestHash()
{
return destHash;
}
private int calculateHash()
{
int b = 0;
for (int i = 0; i < id.length; i++)
b ^= id[i];
return (b ^ address.hashCode()) ^ port;
return DataHelper.hashCode(destHash);
}
/**
* The hash code of a PeerID is the exclusive or of all id bytes.
* The hash code of a PeerID is the hashcode of the desthash
*/
@Override
public int hashCode()
@@ -115,18 +164,15 @@ public class PeerID implements Comparable
/**
* Returns true if and only if this peerID and the given peerID have
* the same 20 bytes as ID.
* the same destination hash
*/
public boolean sameID(PeerID pid)
{
boolean equal = true;
for (int i = 0; equal && i < id.length; i++)
equal = id[i] == pid.id[i];
return equal;
return DataHelper.eq(destHash, pid.getDestHash());
}
/**
* Two PeerIDs are equal when they have the same id, address and port.
* Two PeerIDs are equal when they have the same dest hash
*/
@Override
public boolean equals(Object o)
@@ -135,9 +181,7 @@ public class PeerID implements Comparable
{
PeerID pid = (PeerID)o;
return port == pid.port
&& address.equals(pid.address)
&& sameID(pid);
return sameID(pid);
}
else
return false;
@@ -145,6 +189,7 @@ public class PeerID implements Comparable
/**
* Compares port, address and id.
* @deprecated unused? and will NPE now that address can be null?
*/
public int compareTo(Object o)
{
@@ -176,6 +221,8 @@ public class PeerID implements Comparable
@Override
public String toString()
{
if (id == null || address == null)
return "unkn@" + Base64.encode(destHash).substring(0, 6);
int nonZero = 0;
for (int i = 0; i < id.length; i++) {
if (id[i] != 0) {

View File

@@ -20,10 +20,12 @@
package org.klomp.snark;
import java.util.List;
/**
* Listener for Peer events.
*/
public interface PeerListener
interface PeerListener
{
/**
* Called when the connection to the peer has started and the
@@ -145,13 +147,27 @@ public interface PeerListener
*/
int wantPiece(Peer peer, BitField bitfield);
/**
* Called when we are downloading from the peer and may need to ask for
* a new piece. Returns true if wantPiece() or getPartialPiece() would return a piece.
*
* @param peer the Peer that will be asked to provide the piece.
* @param bitfield a BitField containing the pieces that the other
* side has.
*
* @return if we want any of what the peer has
* @since 0.8.2
*/
boolean needPiece(Peer peer, BitField bitfield);
/**
* Called when the peer has disconnected and the peer task may have a partially
* downloaded piece that the PeerCoordinator can save
*
* @param state the PeerState for the peer
* @param peer the peer
* @since 0.8.2
*/
void savePeerPartial(PeerState state); /* FIXME Exporting non-public type through public API FIXME */
void savePartialPieces(Peer peer, List<PartialPiece> pcs);
/**
* Called when a peer has connected and there may be a partially
@@ -160,13 +176,7 @@ public interface PeerListener
* @param havePieces the have-pieces bitmask for the peer
*
* @return request (contains the partial data and valid length)
* @since 0.8.2
*/
Request getPeerPartial(BitField havePieces); /* FIXME Exporting non-public type through public API FIXME */
/** Mark a peer's requested pieces unrequested when it is disconnected
* This prevents premature end game
*
* @param peer the peer that is disconnecting
*/
void markUnrequested(Peer peer);
PartialPiece getPartialPiece(Peer peer, BitField havePieces);
}

View File

@@ -20,19 +20,27 @@
package org.klomp.snark;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
class PeerState
import org.klomp.snark.bencode.BDecoder;
import org.klomp.snark.bencode.BEValue;
class PeerState implements DataLoader
{
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerState.class);
final Peer peer;
private final Peer peer;
final PeerListener listener;
final MetaInfo metainfo;
private final MetaInfo metainfo;
// Interesting and choking describes whether we are interested in or
// are choking the other side.
@@ -48,6 +56,7 @@ class PeerState
long downloaded;
long uploaded;
/** the pieces the peer has */
BitField bitfield;
// Package local for use by Peer.
@@ -55,12 +64,11 @@ class PeerState
final PeerConnectionOut out;
// Outstanding request
private final List outstandingRequests = new ArrayList();
private final List<Request> outstandingRequests = new ArrayList();
/** the tail (NOT the head) of the request queue */
private Request lastRequest = null;
// If we have te resend outstanding requests (true after we got choked).
private boolean resend = false;
// FIXME if piece size < PARTSIZE, pipeline could be bigger
private final static int MAX_PIPELINE = 5; // this is for outbound requests
private final static int MAX_PIPELINE_BYTES = 128*1024; // this is for inbound requests
public final static int PARTSIZE = 16*1024; // outbound request
@@ -91,14 +99,27 @@ class PeerState
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " rcv " + (choke ? "" : "un") + "choked");
boolean resend = choked && !choke;
choked = choke;
if (choked)
resend = true;
listener.gotChoke(peer, choke);
if (!choked && interesting)
request();
if (interesting && !choked)
request(resend);
if (choked) {
out.cancelRequestMessages();
// old Roberts thrash us here, choke+unchoke right together
// The only problem with returning the partials to the coordinator
// is that chunks above a missing request are lost.
// Future enhancements to PartialPiece could keep track of the holes.
List<PartialPiece> pcs = returnPartialPieces();
if (!pcs.isEmpty()) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " got choked, returning partial pieces to the PeerCoordinator: " + pcs);
listener.savePartialPieces(this.peer, pcs);
}
}
}
void interestedMessage(boolean interest)
@@ -204,13 +225,28 @@ class PeerState
return;
}
if (_log.shouldLog(Log.INFO))
_log.info("Queueing (" + piece + ", " + begin + ", "
+ length + ")" + " to " + peer);
// don't load the data into mem now, let PeerConnectionOut do it
out.sendPiece(piece, begin, length, this);
}
/**
* This is the callback that PeerConnectionOut calls
*
* @return bytes or null for errors
* @since 0.8.2
*/
public byte[] loadData(int piece, int begin, int length) {
byte[] pieceBytes = listener.gotRequest(peer, piece, begin, length);
if (pieceBytes == null)
{
// XXX - Protocol error-> diconnect?
if (_log.shouldLog(Log.WARN))
_log.warn("Got request for unknown piece: " + piece);
return;
return null;
}
// More sanity checks
@@ -222,13 +258,13 @@ class PeerState
+ ", " + begin
+ ", " + length
+ "' message from " + peer);
return;
return null;
}
if (_log.shouldLog(Log.INFO))
_log.info("Sending (" + piece + ", " + begin + ", "
+ length + ")" + " to " + peer);
out.sendPiece(piece, begin, length, pieceBytes);
return pieceBytes;
}
/**
@@ -243,11 +279,16 @@ class PeerState
// This is used to flag that we have to back up from the firstOutstandingRequest
// when calculating how far we've gotten
Request pendingRequest = null;
private Request pendingRequest;
/**
* Called when a partial piece request has been handled by
* Called when a full chunk (i.e. a piece message) has been received by
* PeerConnectionIn.
*
* This may block quite a while if it is the last chunk for a piece,
* as it calls the listener, who stores the piece and then calls
* havePiece for every peer on the torrent (including us).
*
*/
void pieceMessage(Request req)
{
@@ -255,11 +296,15 @@ class PeerState
downloaded += size;
listener.downloaded(peer, size);
pendingRequest = null;
if (_log.shouldLog(Log.DEBUG))
_log.debug("got end of Chunk("
+ req.piece + "," + req.off + "," + req.len + ") from "
+ peer);
// Last chunk needed for this piece?
if (getFirstOutstandingRequest(req.piece) == -1)
{
// warning - may block here for a while
if (listener.gotPiece(peer, req.piece, req.bs))
{
if (_log.shouldLog(Log.DEBUG))
@@ -270,30 +315,40 @@ class PeerState
if (_log.shouldLog(Log.WARN))
_log.warn("Got BAD " + req.piece + " from " + peer);
// XXX ARGH What now !?!
// FIXME Why would we set downloaded to 0?
downloaded = 0;
}
}
// ok done with this one
synchronized(this) {
pendingRequest = null;
}
}
/**
* @return index in outstandingRequests or -1
*/
synchronized private int getFirstOutstandingRequest(int piece)
{
{
for (int i = 0; i < outstandingRequests.size(); i++)
if (((Request)outstandingRequests.get(i)).piece == piece)
if (outstandingRequests.get(i).piece == piece)
return i;
return -1;
}
/**
* Called when a piece message is being processed by the incoming
* connection. Returns null when there was no such request. It also
* connection. That is, when the header of the piece message was received.
* Returns null when there was no such request. It also
* requeues/sends requests when it thinks that they must have been
* lost.
*/
Request getOutstandingRequest(int piece, int begin, int length)
{
if (_log.shouldLog(Log.DEBUG))
_log.debug("getChunk("
+ piece + "," + begin + "," + length + ") "
_log.debug("got start of Chunk("
+ piece + "," + begin + "," + length + ") from "
+ peer);
int r = getFirstOutstandingRequest(piece);
@@ -313,12 +368,12 @@ class PeerState
Request req;
synchronized(this)
{
req = (Request)outstandingRequests.get(r);
req = outstandingRequests.get(r);
while (req.piece == piece && req.off != begin
&& r < outstandingRequests.size() - 1)
{
r++;
req = (Request)outstandingRequests.get(r);
req = outstandingRequests.get(r);
}
// Something wrong?
@@ -333,6 +388,9 @@ class PeerState
downloaded = 0; // XXX - punishment?
return null;
}
// note that this request is being read
pendingRequest = req;
// Report missing requests.
if (r != 0)
@@ -342,7 +400,7 @@ class PeerState
+ ", wanted for peer: " + peer);
for (int i = 0; i < r; i++)
{
Request dropReq = (Request)outstandingRequests.remove(0);
Request dropReq = outstandingRequests.remove(0);
outstandingRequests.add(dropReq);
if (!choked)
out.sendRequest(dropReq);
@@ -356,56 +414,64 @@ class PeerState
// Request more if necessary to keep the pipeline filled.
addRequest();
pendingRequest = req;
return req;
}
// get longest partial piece
Request getPartialRequest()
{
Request req = null;
for (int i = 0; i < outstandingRequests.size(); i++) {
Request r1 = (Request)outstandingRequests.get(i);
int j = getFirstOutstandingRequest(r1.piece);
if (j == -1)
continue;
Request r2 = (Request)outstandingRequests.get(j);
if (r2.off > 0 && ((req == null) || (r2.off > req.off)))
req = r2;
}
if (pendingRequest != null && req != null && pendingRequest.off < req.off) {
if (pendingRequest.off != 0)
req = pendingRequest;
else
req = null;
}
return req;
}
// return array of pieces terminated by -1
// remove most duplicates
// but still could be some duplicates, not guaranteed
int[] getRequestedPieces()
{
int size = outstandingRequests.size();
int[] arr = new int[size+2];
int pc = -1;
int pos = 0;
if (pendingRequest != null) {
pc = pendingRequest.piece;
arr[pos++] = pc;
}
Request req = null;
for (int i = 0; i < size; i++) {
Request r1 = (Request)outstandingRequests.get(i);
if (pc != r1.piece) {
pc = r1.piece;
arr[pos++] = pc;
/**
* @return lowest offset of any request for the piece
* @since 0.8.2
*/
synchronized private Request getLowestOutstandingRequest(int piece) {
Request rv = null;
int lowest = Integer.MAX_VALUE;
for (Request r : outstandingRequests) {
if (r.piece == piece && r.off < lowest) {
lowest = r.off;
rv = r;
}
}
}
arr[pos] = -1;
return(arr);
if (pendingRequest != null &&
pendingRequest.piece == piece && pendingRequest.off < lowest)
rv = pendingRequest;
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " lowest for " + piece + " is " + rv + " out of " + pendingRequest + " and " + outstandingRequests);
return rv;
}
/**
* Get partial pieces, give them back to PeerCoordinator.
* Clears the request queue.
* @return List of PartialPieces, even those with an offset == 0, or empty list
* @since 0.8.2
*/
synchronized List<PartialPiece> returnPartialPieces()
{
Set<Integer> pcs = getRequestedPieces();
List<PartialPiece> rv = new ArrayList(pcs.size());
for (Integer p : pcs) {
Request req = getLowestOutstandingRequest(p.intValue());
if (req != null)
rv.add(new PartialPiece(req));
}
outstandingRequests.clear();
pendingRequest = null;
lastRequest = null;
return rv;
}
/**
* @return all pieces we are currently requesting, or empty Set
*/
synchronized private Set<Integer> getRequestedPieces() {
Set<Integer> rv = new HashSet(outstandingRequests.size() + 1);
for (Request req : outstandingRequests) {
rv.add(Integer.valueOf(req.piece));
if (pendingRequest != null)
rv.add(Integer.valueOf(pendingRequest.piece));
}
return rv;
}
void cancelMessage(int piece, int begin, int length)
@@ -416,6 +482,27 @@ class PeerState
out.cancelRequest(piece, begin, length);
}
/** @since 0.8.2 */
void extensionMessage(int id, byte[] bs)
{
if (id == 0) {
InputStream is = new ByteArrayInputStream(bs);
try {
BDecoder dec = new BDecoder(is);
BEValue bev = dec.bdecodeMap();
Map map = bev.getMap();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got extension handshake message " + bev.toString());
} catch (Exception e) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Failed extension decode", e);
}
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got extended message type: " + id + " length: " + bs.length);
}
}
void unknownMessage(int type, byte[] bs)
{
if (_log.shouldLog(Log.WARN))
@@ -423,22 +510,48 @@ class PeerState
+ " length: " + bs.length);
}
/**
* We now have this piece.
* Tell the peer and cancel any requests for the piece.
*/
void havePiece(int piece)
{
if (_log.shouldLog(Log.DEBUG))
_log.debug("Tell " + peer + " havePiece(" + piece + ")");
synchronized(this)
{
// Tell the other side that we are no longer interested in any of
// the outstanding requests for this piece.
cancelPiece(piece);
// Tell the other side that we really have this piece.
out.sendHave(piece);
// Request something else if necessary.
addRequest();
/**** taken care of in addRequest()
synchronized(this)
{
// Is the peer still interesting?
if (lastRequest == null)
setInteresting(false);
}
****/
}
/**
* Tell the other side that we are no longer interested in any of
* the outstanding requests (if any) for this piece.
* @since 0.8.1
*/
synchronized void cancelPiece(int piece) {
if (lastRequest != null && lastRequest.piece == piece)
lastRequest = null;
Iterator it = outstandingRequests.iterator();
Iterator<Request> it = outstandingRequests.iterator();
while (it.hasNext())
{
Request req = (Request)it.next();
Request req = it.next();
if (req.piece == piece)
{
it.remove();
@@ -447,32 +560,39 @@ class PeerState
out.sendCancel(req);
}
}
}
// Tell the other side that we really have this piece.
out.sendHave(piece);
// Request something else if necessary.
addRequest();
synchronized(this)
{
// Is the peer still interesting?
if (lastRequest == null)
setInteresting(false);
}
}
// Starts or resumes requesting pieces.
private void request()
/**
* Are we currently requesting the piece?
* @deprecated deadlocks
* @since 0.8.1
*/
synchronized boolean isRequesting(int piece) {
if (pendingRequest != null && pendingRequest.piece == piece)
return true;
for (Request req : outstandingRequests) {
if (req.piece == piece)
return true;
}
return false;
}
/**
* Starts or resumes requesting pieces.
* @param resend should we resend outstanding requests?
*/
private void request(boolean resend)
{
// Are there outstanding requests that have to be resend?
if (resend)
{
synchronized (this) {
out.sendRequests(outstandingRequests);
if (!outstandingRequests.isEmpty()) {
out.sendRequests(outstandingRequests);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Resending requests to " + peer + outstandingRequests);
}
}
resend = false;
}
// Add/Send some more requests if necessary.
@@ -481,17 +601,53 @@ class PeerState
/**
* Adds a new request to the outstanding requests list.
* Then send interested if we weren't.
* Then send new requests if not choked.
* If nothing to request, send not interested if we were.
*
* This is called from several places:
*<pre>
* By getOustandingRequest() when the first part of a chunk comes in
* By havePiece() when somebody got a new piece completed
* By chokeMessage() when we receive an unchoke
* By setInteresting() when we are now interested
* By PeerCoordinator.updatePiecePriorities()
*</pre>
*/
synchronized private void addRequest()
synchronized void addRequest()
{
// no bitfield yet? nothing to request then.
if (bitfield == null)
return;
boolean more_pieces = true;
while (more_pieces)
{
more_pieces = outstandingRequests.size() < MAX_PIPELINE;
// We want something and we don't have outstanding requests?
if (more_pieces && lastRequest == null)
if (more_pieces && lastRequest == null) {
// we have nothing in the queue right now
if (!interesting) {
// If we need something, set interesting but delay pulling
// a request from the PeerCoordinator until unchoked.
if (listener.needPiece(this.peer, bitfield)) {
setInteresting(true);
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we need something, setting interesting, delaying requestNextPiece()");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() needs nothing");
}
return;
}
if (choked) {
// If choked, delay pulling
// a request from the PeerCoordinator until unchoked.
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we are choked, delaying requestNextPiece()");
return;
}
more_pieces = requestNextPiece();
else if (more_pieces) // We want something
} else if (more_pieces) // We want something
{
int pieceLength;
boolean isLastChunk;
@@ -519,6 +675,10 @@ class PeerState
}
}
// failsafe
if (interesting && lastRequest == null && outstandingRequests.isEmpty())
setInteresting(false);
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " requests " + outstandingRequests);
}
@@ -526,38 +686,35 @@ class PeerState
/**
* Starts requesting first chunk of next piece. Returns true if
* something has been added to the requests, false otherwise.
* Caller should synchronize.
*/
private boolean requestNextPiece()
{
// Check that we already know what the other side has.
if (bitfield != null)
{
if (bitfield != null) {
// Check for adopting an orphaned partial piece
Request r = listener.getPeerPartial(bitfield);
if (r != null) {
// Check that r not already in outstandingRequests
int[] arr = getRequestedPieces();
boolean found = false;
for (int i = 0; arr[i] >= 0; i++) {
if (arr[i] == r.piece) {
found = true;
break;
}
}
if (!found) {
PartialPiece pp = listener.getPartialPiece(peer, bitfield);
if (pp != null) {
// Double-check that r not already in outstandingRequests
if (!getRequestedPieces().contains(Integer.valueOf(pp.getPiece()))) {
Request r = pp.getRequest();
outstandingRequests.add(r);
if (!choked)
out.sendRequest(r);
lastRequest = r;
return true;
}
}
}
/******* getPartialPiece() does it all now
// Note that in addition to the bitfield, PeerCoordinator uses
// its request tracking and isRequesting() to determine
// what piece to give us next.
int nextPiece = listener.wantPiece(peer, bitfield);
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " want piece " + nextPiece);
if (nextPiece != -1
&& (lastRequest == null || lastRequest.piece != nextPiece))
{
if (nextPiece != -1
&& (lastRequest == null || lastRequest.piece != nextPiece)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " want piece " + nextPiece);
// Fail safe to make sure we are interested
// When we transition into the end game we may not be interested...
if (!interesting) {
@@ -584,34 +741,49 @@ class PeerState
out.sendRequest(req);
lastRequest = req;
return true;
}
}
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " no more pieces to request");
}
*******/
}
// failsafe
if (outstandingRequests.isEmpty())
lastRequest = null;
// If we are not in the end game, we may run out of things to request
// because we are asking other peers. Set not-interesting now rather than
// wait for those other requests to be satisfied via havePiece()
if (interesting && lastRequest == null) {
interesting = false;
out.sendInterest(false);
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " nothing more to request, now uninteresting");
}
return false;
}
synchronized void setInteresting(boolean interest)
{
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " setInteresting(" + interest + ")");
if (interest != interesting)
{
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " setInteresting(" + interest + ")");
interesting = interest;
out.sendInterest(interest);
if (interesting && !choked)
request();
request(true); // we shouldnt have any pending requests, but if we do, resend them
}
}
synchronized void setChoking(boolean choke)
{
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " setChoking(" + choke + ")");
if (choking != choke)
{
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " setChoking(" + choke + ")");
choking = choke;
out.sendChoke(choke);
}
@@ -627,4 +799,16 @@ class PeerState
if (interesting && !choked)
out.retransmitRequests(outstandingRequests);
}
/**
* debug
* @return string or null
* @since 0.8.1
*/
synchronized String getRequests() {
if (outstandingRequests.isEmpty())
return null;
else
return outstandingRequests.toString();
}
}

View File

@@ -1,22 +1,35 @@
package org.klomp.snark;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class Piece implements Comparable {
/**
* This class is used solely by PeerCoordinator.
* Caller must synchronize on many of these methods.
*/
class Piece implements Comparable {
private int id;
private Set 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 = Collections.synchronizedSet(new HashSet());
this.requested = false;
this.peers = new HashSet(I2PSnarkUtil.MAX_CONNECTIONS);
// defer creating requests to save memory
}
/**
* Highest priority first,
* then rarest first
*/
public int compareTo(Object o) throws ClassCastException {
int pdiff = ((Piece)o).priority - this.priority; // reverse
if (pdiff != 0)
return pdiff;
return this.peers.size() - ((Piece)o).peers.size();
}
@@ -37,12 +50,64 @@ public class Piece implements Comparable {
}
public int getId() { return this.id; }
public Set 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; }
/** @since 0.8.1 */
public void setPriority(int p) { this.priority = p; }
/** @since 0.8.1 */
public boolean isDisabled() { return this.priority < 0; }
/** @since 0.8.1 */
public void setDisabled() { this.priority = -1; }
@Override
public String toString() {
return String.valueOf(id);

View File

@@ -22,6 +22,7 @@ package org.klomp.snark;
/**
* Holds all information needed for a partial piece request.
* This class should be used only by PeerState, PeerConnectionIn, and PeerConnectionOut.
*/
class Request
{

View File

@@ -437,7 +437,7 @@ public class Snark
try { storage.close(); } catch (IOException ioee) {
ioee.printStackTrace();
}
fatal("Could not create storage", ioe);
fatal("Could not check or create storage", ioe);
}
}
@@ -745,7 +745,7 @@ public class Snark
_util.debug(s, level, null);
}
/** coordinatorListener */
/** CoordinatorListener - this does nothing */
public void peerChange(PeerCoordinator coordinator, Peer peer)
{
// System.out.println(peer.toString());

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@ import java.util.List;
import java.util.StringTokenizer;
import net.i2p.crypto.SHA1;
import net.i2p.util.SecureFile;
/**
* Maintains pieces on disk. Can be used to store and retrieve pieces.
@@ -42,6 +43,8 @@ public class Storage
private Object[] RAFlock; // lock on RAF access
private long[] RAFtime; // when was RAF last accessed, or 0 if closed
private File[] RAFfile; // File to make it easier to reopen
/** priorities by file; default 0; may be null. @since 0.8.1 */
private int[] priorities;
private final StorageListener listener;
private I2PSnarkUtil _util;
@@ -228,6 +231,8 @@ public class Storage
RAFlock = new Object[size];
RAFtime = new long[size];
RAFfile = new File[size];
priorities = new int[size];
int i = 0;
Iterator it = files.iterator();
@@ -330,6 +335,102 @@ public class Storage
return -1;
}
/**
* @param file canonical path (non-directory)
* @since 0.8.1
*/
public int getPriority(String file) {
if (complete() || metainfo.getFiles() == null || priorities == null)
return 0;
for (int i = 0; i < rafs.length; i++) {
File f = RAFfile[i];
// use canonical in case snark dir or sub dirs are symlinked
if (f != null) {
try {
String canonical = f.getCanonicalPath();
if (canonical.equals(file))
return priorities[i];
} catch (IOException ioe) {}
}
}
return 0;
}
/**
* Must call setPiecePriorities() after calling this
* @param file canonical path (non-directory)
* @param pri default 0; <0 to disable
* @since 0.8.1
*/
public void setPriority(String file, int pri) {
if (complete() || metainfo.getFiles() == null || priorities == null)
return;
for (int i = 0; i < rafs.length; i++) {
File f = RAFfile[i];
// use canonical in case snark dir or sub dirs are symlinked
if (f != null) {
try {
String canonical = f.getCanonicalPath();
if (canonical.equals(file)) {
priorities[i] = pri;
return;
}
} catch (IOException ioe) {}
}
}
}
/**
* Get the file priorities array.
* @return null on error, if complete, or if only one file
* @since 0.8.1
*/
public int[] getFilePriorities() {
return priorities;
}
/**
* Set the file priorities array.
* Only call this when stopped, but after check()
* @param p may be null
* @since 0.8.1
*/
void setFilePriorities(int[] p) {
priorities = p;
}
/**
* Call setPriority() for all changed files first,
* then call this.
* Set the piece priority to the highest priority
* of all files spanning the piece.
* Caller must pass array to the PeerCoordinator.
* @return null on error, if complete, or if only one file
* @since 0.8.1
*/
public int[] getPiecePriorities() {
if (complete() || metainfo.getFiles() == null || priorities == null)
return null;
int[] rv = new int[metainfo.getPieces()];
int file = 0;
long pcEnd = -1;
long fileEnd = lengths[0] - 1;
int psz = metainfo.getPieceLength(0);
for (int i = 0; i < rv.length; i++) {
pcEnd += psz;
int pri = priorities[file];
while (fileEnd <= pcEnd && file < lengths.length - 1) {
file++;
long oldFileEnd = fileEnd;
fileEnd += lengths[file];
if (priorities[file] > pri && oldFileEnd < pcEnd)
pri = priorities[file];
}
rv[i] = pri;
}
return rv;
}
/**
* The BitField that tells which pieces this storage contains.
* Do not change this since this is the current state of the storage.
@@ -362,7 +463,7 @@ public class Storage
/** use a saved bitfield and timestamp from a config file */
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
{
File base = new File(rootDir, filterName(metainfo.getName()));
File base = new SecureFile(rootDir, filterName(metainfo.getName()));
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
List files = metainfo.getFiles();
@@ -413,7 +514,7 @@ public class Storage
RAFfile[i] = f;
total += lengths[i];
if (useSavedBitField) {
long lm = base.lastModified();
long lm = f.lastModified();
if (lm <= 0 || lm > savedTime)
useSavedBitField = false;
}
@@ -436,10 +537,14 @@ public class Storage
changed = true;
checkCreateFiles();
}
if (complete())
if (complete()) {
_util.debug("Torrent is complete", Snark.NOTICE);
else
} else {
// fixme saved priorities
if (files != null)
priorities = new int[files.size()];
_util.debug("Still need " + needed + " out of " + metainfo.getPieces() + " pieces", Snark.NOTICE);
}
}
/**
@@ -519,7 +624,7 @@ public class Storage
else
{
// The final element (file) in the hierarchy.
f = new File(base, name);
f = new SecureFile(base, name);
if (!f.createNewFile() && !f.exists())
throw new IOException("Could not create file " + f);
}
@@ -565,6 +670,10 @@ public class Storage
changed = true;
synchronized(RAFlock[i]) {
allocateFile(i);
// close as we go so we don't run out of file descriptors
try {
closeRAF(i);
} catch (IOException ioe) {}
}
} else {
_util.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR);
@@ -573,8 +682,10 @@ public class Storage
synchronized(RAFlock[i]) {
checkRAF(i);
rafs[i].setLength(lengths[i]);
try {
closeRAF(i);
} catch (IOException ioe) {}
}
// will be closed below
}
}
@@ -583,10 +694,25 @@ public class Storage
{
pieces = metainfo.getPieces();
byte[] piece = new byte[metainfo.getPieceLength(0)];
int file = 0;
long fileEnd = lengths[0];
long pieceEnd = 0;
for (int i = 0; i < pieces; i++)
{
int length = getUncheckedPiece(i, piece);
boolean correctHash = metainfo.checkPiece(i, piece, 0, length);
// close as we go so we don't run out of file descriptors
pieceEnd += length;
while (fileEnd <= pieceEnd) {
synchronized(RAFlock[file]) {
try {
closeRAF(file);
} catch (IOException ioe) {}
}
if (++file >= rafs.length)
break;
fileEnd += lengths[file];
}
if (correctHash)
{
bitfield.set(i);
@@ -601,13 +727,14 @@ public class Storage
_probablyComplete = complete();
// close all the files so we don't end up with a zillion open ones;
// we will reopen as needed
for (int i = 0; i < rafs.length; i++) {
synchronized(RAFlock[i]) {
try {
closeRAF(i);
} catch (IOException ioe) {}
}
}
// Now closed above to avoid running out of file descriptors
//for (int i = 0; i < rafs.length; i++) {
// synchronized(RAFlock[i]) {
// try {
// closeRAF(i);
// } catch (IOException ioe) {}
// }
//}
if (listener != null) {
listener.storageAllChecked(this);
@@ -616,6 +743,7 @@ public class Storage
}
}
/** this calls openRAF(); caller must synnchronize and call closeRAF() */
private void allocateFile(int nr) throws IOException
{
// caller synchronized
@@ -624,7 +752,12 @@ public class Storage
// the whole file?
listener.storageCreateFile(this, names[nr], lengths[nr]);
final int ZEROBLOCKSIZE = metainfo.getPieceLength(0);
byte[] zeros = new byte[ZEROBLOCKSIZE];
byte[] zeros;
try {
zeros = new byte[ZEROBLOCKSIZE];
} catch (OutOfMemoryError oom) {
throw new IOException(oom.toString());
}
int i;
for (i = 0; i < lengths[nr]/ZEROBLOCKSIZE; i++)
{

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;
@@ -266,15 +268,15 @@ public class TrackerClient extends I2PAppThread
// we only want to talk to new people if we need things
// from them (duh)
List ordered = new ArrayList(peers);
Collections.shuffle(ordered);
Collections.shuffle(ordered, r);
Iterator it = ordered.iterator();
while (it.hasNext()) {
while ((!stop) && it.hasNext()) {
Peer cur = (Peer)it.next();
// FIXME if id == us || dest == us continue;
// 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) {}
@@ -357,6 +359,7 @@ public class TrackerClient extends I2PAppThread
+ "&uploaded=" + uploaded
+ "&downloaded=" + downloaded
+ "&left=" + left
+ "&compact=1" // NOTE: opentracker will return 400 for &compact alone
+ ((! event.equals(NO_EVENT)) ? ("&event=" + event) : "");
if (left <= 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
s += "&numwant=0";

View File

@@ -24,7 +24,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -33,11 +32,17 @@ import org.klomp.snark.bencode.BDecoder;
import org.klomp.snark.bencode.BEValue;
import org.klomp.snark.bencode.InvalidBEncodingException;
/**
* The data structure for the tracker response.
* Handles both traditional and compact formats.
* Compact format 1 - a list of hashes - early format for testing
* Compact format 2 - One big string of concatenated hashes - official format
*/
public class TrackerInfo
{
private final String failure_reason;
private final int interval;
private final Set peers;
private final Set<Peer> peers;
private int complete;
private int incomplete;
@@ -73,10 +78,19 @@ public class TrackerInfo
interval = beInterval.getInt();
BEValue bePeers = (BEValue)m.get("peers");
if (bePeers == null)
if (bePeers == null) {
peers = Collections.EMPTY_SET;
else
peers = getPeers(bePeers.getList(), my_id, metainfo);
} else {
Set<Peer> p;
try {
// One big string (the official compact format)
p = getPeers(bePeers.getBytes(), my_id, metainfo);
} catch (InvalidBEncodingException ibe) {
// List of Dictionaries or List of Strings
p = getPeers(bePeers.getList(), my_id, metainfo);
}
peers = p;
}
BEValue bev = (BEValue)m.get("complete");
if (bev != null) try {
@@ -94,32 +108,68 @@ public class TrackerInfo
}
}
public static Set getPeers(InputStream in, byte[] my_id, MetaInfo metainfo)
/******
public static Set<Peer> getPeers(InputStream in, byte[] my_id, MetaInfo metainfo)
throws IOException
{
return getPeers(new BDecoder(in), my_id, metainfo);
}
public static Set getPeers(BDecoder be, byte[] my_id, MetaInfo metainfo)
public static Set<Peer> getPeers(BDecoder be, byte[] my_id, MetaInfo metainfo)
throws IOException
{
return getPeers(be.bdecodeList().getList(), my_id, metainfo);
}
******/
public static Set getPeers(List l, byte[] my_id, MetaInfo metainfo)
/** List of Dictionaries or List of Strings */
private static Set<Peer> getPeers(List<BEValue> l, byte[] my_id, MetaInfo metainfo)
throws IOException
{
Set peers = new HashSet(l.size());
Set<Peer> peers = new HashSet(l.size());
Iterator it = l.iterator();
while (it.hasNext())
{
for (BEValue bev : l) {
PeerID peerID;
try {
peerID = new PeerID(((BEValue)it.next()).getMap());
// Case 1 - non-compact - A list of dictionaries (maps)
peerID = new PeerID(bev.getMap());
} catch (InvalidBEncodingException ibe) {
// don't let one bad entry spoil the whole list
//Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
try {
// Case 2 - compact - A list of 32-byte binary strings (hashes)
// This was just for testing and is not the official format
peerID = new PeerID(bev.getBytes());
} catch (InvalidBEncodingException ibe2) {
// don't let one bad entry spoil the whole list
//Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
continue;
}
}
peers.add(new Peer(peerID, my_id, metainfo));
}
return peers;
}
private static final int HASH_LENGTH = 32;
/**
* One big string of concatenated 32-byte hashes
* @since 0.8.1
*/
private static Set<Peer> getPeers(byte[] l, byte[] my_id, MetaInfo metainfo)
throws IOException
{
int count = l.length / HASH_LENGTH;
Set<Peer> peers = new HashSet(count);
for (int i = 0; i < count; i++) {
PeerID peerID;
byte[] hash = new byte[HASH_LENGTH];
System.arraycopy(l, i * HASH_LENGTH, hash, 0, HASH_LENGTH);
try {
peerID = new PeerID(hash);
} catch (InvalidBEncodingException ibe) {
// won't happen
continue;
}
peers.add(new Peer(peerID, my_id, metainfo));
@@ -128,7 +178,7 @@ public class TrackerInfo
return peers;
}
public Set getPeers()
public Set<Peer> getPeers()
{
return peers;
}

View File

@@ -140,7 +140,7 @@ public class BEValue
* succeeds when the BEValue is actually a List, otherwise it will
* throw a InvalidBEncodingException.
*/
public List getList() throws InvalidBEncodingException
public List<BEValue> getList() throws InvalidBEncodingException
{
try
{
@@ -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 getMap() throws InvalidBEncodingException
public Map<String, BEValue> getMap() throws InvalidBEncodingException
{
try
{

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,862 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2psnark package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
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: 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"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:94
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "Se añaden los torrents en {0} minutos ..."
#: ../java/src/org/klomp/snark/SnarkManager.java:296
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Límite del número total de subidores cambiado a {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:298
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "El límite mínimo de subidores es {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:310
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Ancho de banda para la subida ha sido cambiado a {0} kbyte/s."
#: ../java/src/org/klomp/snark/SnarkManager.java:312
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "El límite mínimo de ancho de banda para la subida está en {0} kbyte/s."
#: ../java/src/org/klomp/snark/SnarkManager.java:324
#, java-format
msgid "Startup delay limit changed to {0} minutes"
msgstr "Demora del arranque cambiado a {0} minutos"
#: ../java/src/org/klomp/snark/SnarkManager.java:371
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr "Cambios de I2CP y del túnel tomarán efecto despues de detener todos los torrents."
#: ../java/src/org/klomp/snark/SnarkManager.java:378
msgid "Disconnecting old I2CP destination"
msgstr "Desconectando anterior Destino I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:382
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "Preferencias de I2CP cambiadas a {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:386
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "Conectarse no fue posíble con las nuevas preferencias I2CP, utilizaré las anteriores."
#: ../java/src/org/klomp/snark/SnarkManager.java:390
msgid "Unable to reconnect with the old settings!"
msgstr "Conectarse usando las preferencias anteriores no fue posible!"
#: ../java/src/org/klomp/snark/SnarkManager.java:392
msgid "Reconnected on the new I2CP destination"
msgstr "Conectado con la nueva Destino I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:403
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "Conexión I2CP reestablecida para \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:414
msgid "Enabled autostart"
msgstr "Arranque automático activado"
#: ../java/src/org/klomp/snark/SnarkManager.java:416
msgid "Disabled autostart"
msgstr "Arranque automático desactivado"
#: ../java/src/org/klomp/snark/SnarkManager.java:422
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "Rastreadores abiertos activados - Para aplicar ello es necesario que reinicies los torrents."
#: ../java/src/org/klomp/snark/SnarkManager.java:424
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "Rastreadores abiertos desactivados - Para aplicar ello es necesario que reinicies los torrents."
#: ../java/src/org/klomp/snark/SnarkManager.java:431
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "Lista de rastreadores abiertos cambiada - Para aplicar ello es necesario que reinicies los torrents."
#: ../java/src/org/klomp/snark/SnarkManager.java:438
#, java-format
msgid "{0} theme loaded, return to main i2psnark page to view."
msgstr "Tema {0} cargado. ¡Vuelve a la página principal de i2psnark para verlo!"
#: ../java/src/org/klomp/snark/SnarkManager.java:445
msgid "Configuration unchanged."
msgstr "Configuración no cambiada."
#: ../java/src/org/klomp/snark/SnarkManager.java:455
#, java-format
msgid "Unable to save the config to {0}"
msgstr "No se pudo guardar la configuración en {0}."
#: ../java/src/org/klomp/snark/SnarkManager.java:494
msgid "Connecting to I2P"
msgstr "Conectando a I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:497
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Error al conectar a I2P - Compruebe su configuración I2CP!"
#: ../java/src/org/klomp/snark/SnarkManager.java:506
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Error: No se ha podido añadir el torrent {0}."
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:528
#, java-format
msgid "Cannot open \"{0}\""
msgstr "No se puede abrir \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:541
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open trackers only"
msgstr "Advertencia - Se ignora rastreado no I2P en \"{0}\", anunciando sólo a los rastreadorse abiertos de I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:543
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are disabled, you must enable open trackers before starting the torrent!"
msgstr "Advertencia - Se ignora rastreado no I2P en \"{0}\", rastreadores abiertos están desactivados. ¡Tienes que activarlos antes de iniciar el torrent!"
#: ../java/src/org/klomp/snark/SnarkManager.java:563
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "El archivo .torrent en \"{0}\" no es válido."
#: ../java/src/org/klomp/snark/SnarkManager.java:578
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Torrent añadido e iniciado: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:580
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Torrent añadido: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:734
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "Hay demasiados archivos en \"{0}\", se borrará ({1}). "
#: ../java/src/org/klomp/snark/SnarkManager.java:736
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "Archivo de datos del torrent \"{0}\" no puede terminar en \".torrent' y será borrado."
#: ../java/src/org/klomp/snark/SnarkManager.java:738
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "No hay partes en \"{0}\", se borrará."
#: ../java/src/org/klomp/snark/SnarkManager.java:740
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "Hay demasiadas partes en \"{0}\" y el límite es {1}. Se borrarán."
#: ../java/src/org/klomp/snark/SnarkManager.java:742
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "Partes en \"{0}\" son demasiado grandes ({1}B). Se borrarán."
#: ../java/src/org/klomp/snark/SnarkManager.java:743
#, java-format
msgid "Limit is {0}B"
msgstr "El límite es de \"{0}\"Bytes"
#: ../java/src/org/klomp/snark/SnarkManager.java:751
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Torrents más grandes que \"{0}\"Bytes aún no funcionan, se borrará \"{1}\"."
#: ../java/src/org/klomp/snark/SnarkManager.java:767
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Error: No se pudo quitar el torrent \"{0}\"."
#: ../java/src/org/klomp/snark/SnarkManager.java:794
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Torrent detenido: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:814
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Torrent quitado: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:852
#, java-format
msgid "Download finished: {0}"
msgstr "Terminada la descarga de \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:880
msgid "Unable to connect to I2P!"
msgstr "Imposible de conectarse con I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:886
#, java-format
msgid "Unable to add {0}"
msgstr "Imposible de añadir {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:185
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - Cliente de BitTorrent Anónimo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:198
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
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:205
msgid "Refresh page"
msgstr "Actualizar página"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:210
msgid "Forum"
msgstr "Foro"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:264
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1483
msgid "Status"
msgstr "Estado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:272
msgid "Hide Peers"
msgstr "ocultar pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:279
msgid "Show Peers"
msgstr "mostrar pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:286
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464
msgid "Torrent"
msgstr "Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:290
msgid "Estimated time remaining"
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 "Tiempo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "Downloaded"
msgstr "Descargado"
#. 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
msgid "RX"
msgstr "Bajado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:304
msgid "Uploaded"
msgstr "Subido"
#. 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
msgid "TX"
msgstr "Subido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:312
msgid "Down Rate"
msgstr "Tasa&nbsp;de descarga"
#. 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
msgid "Rate"
msgstr "Tasa"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:322
msgid "Up Rate"
msgstr "Tasa de subida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:340
msgid "Stop all torrents and the I2P tunnel"
msgstr "Detener todos los torrents y el túnel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
msgid "Stop All"
msgstr "Detener todos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:351
msgid "Start all torrents and the I2P tunnel"
msgstr "Iniciar todos los torrents y el túnel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353
msgid "Start All"
msgstr "Arrancar todos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:372
msgid "No torrents loaded."
msgstr "No está cargado ningún torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
msgid "Totals"
msgstr "Total"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:379
#, 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-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "1 par conectado"
msgstr[1] "{0} pares conectados"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:454
#, java-format
msgid "Fetching {0}"
msgstr "Recogiendo {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458
msgid "Invalid URL - must start with http://"
msgstr "Dirección no válida - tiene que comenzar con http://"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:489
#, java-format
msgid "Starting up torrent {0}"
msgstr "Iniciando el torrent {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:527
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Borrado archivo torrent: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:533
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:543
#, java-format
msgid "Data file deleted: {0}"
msgstr "Borrado el archivo de datos: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:545
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "No se pudo borrar el archivo de datos: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Ha sido borrada la carpeta de datos: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:587
msgid "Error creating torrent - you must select a tracker"
msgstr "Error al crear el torrents - Tienes que elegir un rastreador."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:602
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Torrent creado 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 "Muchos rastreadores en I2P requieren que te registres, antes de que puedas subir el torrent. Por favor, ¡hazlo antes de iniciar \"{0}\"!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:607
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Error al crear el torrent \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:610
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "No se puede crear un torrent para datos inexistentes: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:613
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Error al crear el torrent - Tienes que especificar un archivo o una carpeta."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:616
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Deteniendo todos los torrents y cerrando el túnel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:627
msgid "I2P tunnel closed."
msgstr "Túnel I2P cerrado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:630
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Abriendo el túnel I2P e iniciando los 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
msgid "Tracker Error"
msgstr "Error del rastrador"
#: ../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-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "1 par"
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"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:784
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1533
msgid "Complete"
msgstr "completo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:792
msgid "OK"
msgstr "bien"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801
msgid "Stalled"
msgstr "estancado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
msgid "No Peers"
msgstr "sin pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
msgid "Stopped"
msgstr "detenido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
#, java-format
msgid "Details at {0} tracker"
msgstr "Detalles en el rastreador {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:838
msgid "Info"
msgstr "Info"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:853
msgid "View files"
msgstr "mostrar archivos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:855
msgid "Open file"
msgstr "abrir archivo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:865
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569
msgid "Open"
msgstr "abrir"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:909
msgid "Stop the torrent"
msgstr "Detener el torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:911
msgid "Stop"
msgstr "Detener"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:921
msgid "Start the torrent"
msgstr "Iniciar el torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:923
msgid "Start"
msgstr "Iniciar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Quita el torrent de la lista de los torrents activos borrando el archivo .torrent"
#. 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-format
msgid "Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?"
msgstr "¿Estás seguro de que quieres borrar el archivo \\''{0}.torrent\\''? (Datos bajados no se borrarán.)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:941
msgid "Remove"
msgstr "Quitar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:950
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Borrar el archivo torrent y el/los archivo(s) de datos pertenecientes"
#. 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-format
msgid "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?"
msgstr "¿Estás seguro de que quieres borrar el archivo torrent \\''{0}\\'' y todos los datos descargados de este torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
msgid "Delete"
msgstr "Borrar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:991
msgid "Unknown"
msgstr "desconocido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
msgid "Seed"
msgstr "Sembrador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1019
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "no interesante (El par no tiene partes que nos interesen.)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1021
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "moderado (De momento el par no nos permite solicitar más partes)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1035
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "desinteresado (No tenemos las partes que el par quiere.)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1037
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Moderando (De momento no se le permite al par solicitar más partes)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1092
msgid "Add Torrent"
msgstr "Añadir un torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094
msgid "From URL"
msgstr "URL fuente"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1097
msgid "Torrent file must originate from an I2P-based tracker"
msgstr "El archivo torrent debe incluir un rastreador I2P."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1102
msgid "Add torrent"
msgstr "Añadir torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr "También puedes copiar archivos torrent a {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1107
msgid "Removing a .torrent will cause it to stop."
msgstr "Quitar un archivo torrent resultará en que se detenga el torrent perteneciente."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1131
msgid "Create Torrent"
msgstr "Crear un 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 "Datos para sembrar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1138
msgid "File or directory to seed (must be within the specified path)"
msgstr "Archivo o carpeta para sembrar (tiene que estár en la carpeta especificada)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1140
msgid "Tracker"
msgstr "Rastreador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1142
msgid "Select a tracker"
msgstr "Selecciona un rastreador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1155
msgid "or"
msgstr "o"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1158
msgid "Specify custom tracker announce URL"
msgstr "¡Especifica una URL para anunciar al rastreador!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1161
msgid "Create torrent"
msgstr "Crear torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1180
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1317
msgid "Configuration"
msgstr "Preferencias"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1184
msgid "Data directory"
msgstr "Carpeta de datos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1186
msgid "Edit i2psnark.config and restart to change"
msgstr "Para cambiar, ¡modifica el archivo i2psnark.config y reinicia!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190
msgid "Auto start"
msgstr "Arranque automático"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1194
msgid "If checked, automatically start torrents that are added"
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"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1211
msgid "Startup delay"
msgstr "Demora del arranque"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1213
msgid "minutes"
msgstr "minutos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
msgid "Total uploader limit"
msgstr "Límite global de subidores"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240
msgid "peers"
msgstr "pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244
msgid "Up bandwidth limit"
msgstr "Límite del ancho de banda para la subida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247
msgid "Half available bandwidth recommended."
msgstr "Se recomienda la mitad del ancho de banda disponible."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1249
msgid "View or change router bandwidth"
msgstr "Mostrar y cambiar preferencias del ancho de banda del enrutador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253
msgid "Use open trackers also"
msgstr "Usar también rastreadores abiertos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1257
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
msgstr "Si está marcado, el torrent se anunciará a los rastreadores abiertos, además de a los rastreadores especificados."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261
msgid "Open tracker announce URLs"
msgstr "URL(s) para anunciar a rastreadores abiertos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273
msgid "Inbound Settings"
msgstr "Preferencias de entrada"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279
msgid "Outbound Settings"
msgstr "Preferencias de salida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286
msgid "I2CP host"
msgstr "Anfitrión I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
msgid "I2CP port"
msgstr "Puerto I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1303
msgid "I2CP options"
msgstr "Opciones I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1308
msgid "Save configuration"
msgstr "Guardar ajustes"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1325
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "1 salto"
msgstr[1] "{0} saltos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1326
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "1 túnel"
msgstr[1] "{0} túneles"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1480
msgid "Size"
msgstr "Tamaño"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1487
msgid "Priority"
msgstr "Prioridad"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1492
msgid "Up to higher level directory"
msgstr "Subir una herarquía"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517
msgid "Directory"
msgstr "Carpeta"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1522
msgid "Torrent not found?"
msgstr "¿No se encotró el archivo torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530
msgid "File not found in torrent?"
msgstr "¿Archivo no encontrado en el torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1543
msgid "complete"
msgstr "completo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544
msgid "bytes remaining"
msgstr "Bytes faltando"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1595
msgid "High"
msgstr "alta"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1600
msgid "Normal"
msgstr "normal"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1605
msgid "Skip"
msgstr "dejar de lado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1614
msgid "Save priorities"
msgstr "Guardar prioridades"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent obtenido desde {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1746
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent ya en marcha: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1748
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent ya encolado: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1755
#, java-format
msgid "Failed to copy torrent file to {0}"
msgstr "No se pudo copiar el torrent a {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1759
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Torrent en {0} no era válido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1764
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Torrent no se ha podido obtener de {0}"
#~ msgid " theme locked and loaded."
#~ msgstr "tema cargado"
#~ msgid "Hide All Attached Peers [connected/total in swarm]"
#~ msgstr "Ocultar todos los pares conectados [conectados/todos]"
#~ msgid "Show All Attached Peers [connected/total in swarm]"
#~ msgstr "Mostrar todos los pares conectados [conectados/todos]"
#~ msgid "Loaded Torrents"
#~ msgstr "Torrents"
#~ msgid "Estimated Download Time"
#~ msgstr "tiempo restante de descarga"
#~ msgid "1"
#~ msgid_plural "{0}"
#~ msgstr[0] "{0}"
#~ msgstr[1] "{0}"
#~ msgid "Torrent file {0} does not exist"
#~ msgstr "Archivo del torrent {0} no existe"
#~ msgid "Copying torrent to {0}"
#~ msgstr "Copiando torrent a {0}"
#~ msgid "from {0}"
#~ msgstr "de {0}"
#~ msgid "Downloading"
#~ msgstr "descargando"
#~ msgid "File"
#~ msgstr "Archivo"
#~ msgid "FileSize"
#~ msgstr "Tamaño"
#~ msgid "Download Status"
#~ msgstr "Estado"
#~ msgid "size: {0}B"
#~ msgstr "Tamaño: {0}Bytes"
#~ msgid "Directory to store torrents and data"
#~ msgstr "Carpeta para guardar los archivos torrent y los datos"
#~ msgid "Do not download"
#~ msgstr "No descargues"
#~ msgid "Details"
#~ msgstr "Detalles"
#~ msgid "Cannot change the I2CP settings while torrents are active"
#~ msgstr ""
#~ "No se puede cammbiar los ajustes I2CP mientras estén activos los torrents"
#~ msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
#~ msgstr ""
#~ "Rastreador fuera de I2P en \"{0}\", borrando de la lista de rastreadores"
#~ msgid "{0} torrents"
#~ msgstr "{0} Torrents"
#~ msgid "Uninteresting"
#~ msgstr "no interesante"
#~ msgid "Choked"
#~ msgstr "frenado"
#~ msgid "Uninterested"
#~ msgstr "desinteresado"
#~ msgid "Choking"
#~ msgstr "frenando"
#~ msgid "Custom tracker URL"
#~ msgstr "URL especial del rastreador"
#~ msgid "Configure"
#~ msgstr "Ajustes"

View File

@@ -0,0 +1,855 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2psnark package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-12-28 00:08+0000\n"
"PO-Revision-Date: 2010-12-31 02:22+0100\n"
"Last-Translator: mixxy <m1xxy@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: French\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:94
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "Ajouter des torrents dans {0} minutes"
#: ../java/src/org/klomp/snark/SnarkManager.java:296
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Limite agrégée des uploaders modifiée : {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:298
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "La limite minimale agrégée des uploaders est : {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:310
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "La limite d'upload modifiée : {0} Ko/s"
#: ../java/src/org/klomp/snark/SnarkManager.java:312
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "La limite minimale d'upload est {0} Ko/s"
#: ../java/src/org/klomp/snark/SnarkManager.java:324
#, java-format
msgid "Startup delay limit changed to {0} minutes"
msgstr "Delais de démarrage modifié : {0] minutes"
#: ../java/src/org/klomp/snark/SnarkManager.java:371
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr "Les modifications I2CP et des tunnels seront prise en compte après avoir arrêté tous les torrents"
#: ../java/src/org/klomp/snark/SnarkManager.java:378
msgid "Disconnecting old I2CP destination"
msgstr "Déconnexion des anciennes destination I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:382
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "Les paramètres I2CP ont été changés : {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:386
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "Impossible de se connecter avec les nouveaux paramètres, retour à l'ancienne configuration I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:390
msgid "Unable to reconnect with the old settings!"
msgstr "Impossible de se reconnecter avec les anciens paramètres!"
#: ../java/src/org/klomp/snark/SnarkManager.java:392
msgid "Reconnected on the new I2CP destination"
msgstr "Reconnexion sur la nouvelle destination I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:403
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "Listener I2CP redémarré pour \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:414
msgid "Enabled autostart"
msgstr "Le démarrage automatique est activé"
#: ../java/src/org/klomp/snark/SnarkManager.java:416
msgid "Disabled autostart"
msgstr "Le démarrage automatique est désactivé"
#: ../java/src/org/klomp/snark/SnarkManager.java:422
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "Les open trackers sont activés - ceci a nécessité un redémarrage des torrents pour être pris en compte."
#: ../java/src/org/klomp/snark/SnarkManager.java:424
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "Les open trackers sont désactivés - ceci a nécessité un redémarrage des torrents pour être pris en compte."
#: ../java/src/org/klomp/snark/SnarkManager.java:431
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "Liste des Open trackers modifiée - ceci nécessite un redémarrage des torrents pour être pris en compte"
#: ../java/src/org/klomp/snark/SnarkManager.java:438
#, java-format
msgid "{0} theme loaded, return to main i2psnark page to view."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:445
msgid "Configuration unchanged."
msgstr "La configuration n'a pas été modifiée"
#: ../java/src/org/klomp/snark/SnarkManager.java:455
#, java-format
msgid "Unable to save the config to {0}"
msgstr "Impossible de sauvegarder la configuration vers {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:494
msgid "Connecting to I2P"
msgstr "Connexion à I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:497
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Erreur de connexion à I2P - Vérifiez vos paramètres I2CP!"
#: ../java/src/org/klomp/snark/SnarkManager.java:506
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Erreur : Impossible d'ajouter le torrent : {0}"
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:528
#, java-format
msgid "Cannot open \"{0}\""
msgstr "Impossible d'ouvrir: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:541
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open trackers only"
msgstr "Attention - Les trackers non-i2p dans \"{0}\" sont ignorés, seuls les open trackers I2P seront utilisés!"
#: ../java/src/org/klomp/snark/SnarkManager.java:543
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are disabled, you must enable open trackers before starting the torrent!"
msgstr "Attention - Les trackers non-i2p dans \"{0}\" sont ignorés, et les open trackers sont désactivés, vous devez activer les open trackers avant de démarrer le torrent!"
#: ../java/src/org/klomp/snark/SnarkManager.java:563
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "Le torrent dans \"{0}\" est invalide"
#: ../java/src/org/klomp/snark/SnarkManager.java:578
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Torrent ajouté et démarré: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:580
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Torrent ajouté: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:734
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "Trop de fichiers dans \"{0}\" ({1}), suppression! "
#: ../java/src/org/klomp/snark/SnarkManager.java:736
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "Le fichier torrent \"{0}\" ne peut pas se terminer par \".torrent\", suppression!"
#: ../java/src/org/klomp/snark/SnarkManager.java:738
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "Pas de morceaux dans \"{0}\", suppression!"
#: ../java/src/org/klomp/snark/SnarkManager.java:740
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "Trop de morceaux dans \"{0}\" , la limite est {1}, suppression!"
#: ../java/src/org/klomp/snark/SnarkManager.java:742
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "Les morceaux sont trop larges dans \"{0}\" ({1}B), suppresion."
#: ../java/src/org/klomp/snark/SnarkManager.java:743
#, java-format
msgid "Limit is {0}B"
msgstr "La limite est de \"{0}\"Octets"
#: ../java/src/org/klomp/snark/SnarkManager.java:751
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Les torrents dont la taille est supérieure à \"{0}\"Octets ne sont pas encore supportés, suppression \"{1}\"."
#: ../java/src/org/klomp/snark/SnarkManager.java:767
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Erreur: Impossible de supprimer le torrent \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:794
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Torrent arrêté:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:814
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Torrent supprimé:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:852
#, java-format
msgid "Download finished: {0}"
msgstr "Téléchargement terminé:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:880
msgid "Unable to connect to I2P!"
msgstr "Impossible de se connecter à I2P!"
#: ../java/src/org/klomp/snark/SnarkManager.java:886
#, java-format
msgid "Unable to add {0}"
msgstr "Impossible d'ajouter {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:185
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - Client BitTorrent anonyme"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:198
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
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:205
msgid "Refresh page"
msgstr "Rafraîchir la page"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:210
msgid "Forum"
msgstr "Forum"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:264
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1483
msgid "Status"
msgstr "État"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:272
msgid "Hide Peers"
msgstr "Cacher les pairs"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:279
msgid "Show Peers"
msgstr "Afficher les pairs"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:286
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464
msgid "Torrent"
msgstr "Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:290
#, fuzzy
msgid "Estimated time remaining"
msgstr "Octets restants"
# NOTE: purposely left blank to leave more room in the table header
# msgstr "Temps&nbsp;restant"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:293
msgid "ETA"
msgstr " Temps"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "Downloaded"
msgstr "Téléchargé"
#. 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
msgid "RX"
msgstr "Reçu"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:304
msgid "Uploaded"
msgstr "Envoyé"
#. 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
msgid "TX"
msgstr "Envoyé"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:312
msgid "Down Rate"
msgstr "Taux de téléchargement"
#. 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
msgid "Rate"
msgstr "Vitesse"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:322
msgid "Up Rate"
msgstr "Taux d'envoi"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:340
msgid "Stop all torrents and the I2P tunnel"
msgstr "Arrêter tous les torrents et le tunnel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
msgid "Stop All"
msgstr "Arrêter tout"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:351
msgid "Start all torrents and the I2P tunnel"
msgstr "Démarrer tous les torrents et le tunnel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353
msgid "Start All"
msgstr "Démarrer tout"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:372
msgid "No torrents loaded."
msgstr "Aucun torrent chargé."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
msgid "Totals"
msgstr "Totaux"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:379
#, 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-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "1 pair connecté"
msgstr[1] "{0} pairs connectés"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:454
#, java-format
msgid "Fetching {0}"
msgstr "Envoi {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458
msgid "Invalid URL - must start with http://"
msgstr "URL invalide - elle doit débuter par http://"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:489
#, java-format
msgid "Starting up torrent {0}"
msgstr "Démarrage du torrent {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:527
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Fichier torrent effacé: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:533
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:543
#, java-format
msgid "Data file deleted: {0}"
msgstr "Fichier de données effacé: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:545
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Le fichier de données ne peut être effacé: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Répertoire des données effacé: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:587
msgid "Error creating torrent - you must select a tracker"
msgstr "Erreur lors de la création du torrent - vous devez sélectionner un tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:602
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Torrent créé pour \"{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 "De nombreux trackers I2P nécessitent d'enregistrer les nouveaux torrents avant de seeder - faites-le avant de démarrer \"{0}\"!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:607
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Erreur de création du torrent pour \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:610
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Impossible de créer un torrent pour des données inexistantes: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:613
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Erreur de création du torrent - vous devez saisir un fichier ou un répertoire"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:616
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Arrêt de tous les torrents et fermeture du tunnel I2P."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:627
msgid "I2P tunnel closed."
msgstr "Tunnel I2P fermé."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:630
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Ouverture du tunnel I2P and démarrage de tous les 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
msgid "Tracker Error"
msgstr "Erreur du tracker"
#: ../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-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "1 Pair"
msgstr[1] "{0} Pairs"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:775
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:780
msgid "Seeding"
msgstr "Seed en cours"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:784
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1533
msgid "Complete"
msgstr "Complet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:792
msgid "OK"
msgstr "OK"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801
msgid "Stalled"
msgstr "Figé"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
msgid "No Peers"
msgstr "Pas de pair"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
msgid "Stopped"
msgstr "Arrêté"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
#, fuzzy, java-format
msgid "Details at {0} tracker"
msgstr "Sélectionner un tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:838
#, fuzzy
msgid "Info"
msgstr "Ignore"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:853
msgid "View files"
msgstr "Voir les fichiers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:855
msgid "Open file"
msgstr "Ouvrir fichier"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:865
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569
#, fuzzy
msgid "Open"
msgstr "Ouvrir fichier"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:909
msgid "Stop the torrent"
msgstr "Arrêter le torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:911
msgid "Stop"
msgstr "Arrêter"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:921
msgid "Start the torrent"
msgstr "Arrêter le torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:923
msgid "Start"
msgstr "Démarrer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Enlever le torrent de la liste active, suprression du fichier .torrent"
#. 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-format
msgid "Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?"
msgstr "Etes-vous certain de vouloir supprimer le fichier \\''{0}.torrent\\'' (les données déjà téléchargées ne seront pas supprimées) ?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:941
msgid "Remove"
msgstr "Enlever"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:950
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Supprimer le fichier .torrent et le(s) fichier(s) de données associé(s)"
#. 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-format
msgid "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?"
msgstr "Etes-vous certain de vouloir supprimer le torrent \\''{0}\\'' ainsi que toutes les données téléchargées ?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
msgid "Delete"
msgstr "Supprimer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:991
msgid "Unknown"
msgstr "Inconnu"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
msgid "Seed"
msgstr "Seed"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1019
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "aucun intérêt (le pair n'a aucun morceau utile)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1021
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "bridé (le pair ne nous permet pas de demander un morceau)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1035
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "aucun intérêt (nous n'avons aucun morceau utile au pair)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1037
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "bridage (nous ne permettons pas au pair de demander un morceau)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1092
msgid "Add Torrent"
msgstr "Ajouter torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094
msgid "From URL"
msgstr "Depuis l'url"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1097
msgid "Torrent file must originate from an I2P-based tracker"
msgstr "Le fichier torrent doit provenir d'un tracker I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1102
msgid "Add torrent"
msgstr "Ajouter torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr "Vous pouvez aussi copier les fichiers .torrent vers {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1107
msgid "Removing a .torrent will cause it to stop."
msgstr "La suppression d'un fichier .torrent entraine l'arrêt du torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1131
msgid "Create Torrent"
msgstr "Cré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
msgid "Data to seed"
msgstr "Données à seeder"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1138
msgid "File or directory to seed (must be within the specified path)"
msgstr "Fichier ou répertoire à seeder (doit être dans le chemin spécifié)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1140
msgid "Tracker"
msgstr "Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1142
msgid "Select a tracker"
msgstr "Sélectionner un tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1155
msgid "or"
msgstr "ou"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1158
msgid "Specify custom tracker announce URL"
msgstr "Spécifier une URL personnalisée d'annonce de tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1161
msgid "Create torrent"
msgstr "Créer torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1180
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1317
msgid "Configuration"
msgstr "Configuration"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1184
msgid "Data directory"
msgstr "Répertoire de données"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1186
msgid "Edit i2psnark.config and restart to change"
msgstr "Editez i2psnark.config et redémarrez pour prendre en compte les modifications"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190
msgid "Auto start"
msgstr "Démarrage automatique"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1194
msgid "If checked, automatically start torrents that are added"
msgstr "Si coché, les torrents démarrerons automatiquement lors de l'ajout"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1198
msgid "Theme"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1211
msgid "Startup delay"
msgstr "Délais de démarrage"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1213
msgid "minutes"
msgstr "minutes"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
msgid "Total uploader limit"
msgstr "Limite totale d'envoi"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240
msgid "peers"
msgstr "pairs"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244
msgid "Up bandwidth limit"
msgstr "Limite de bande passante en envoi"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247
msgid "Half available bandwidth recommended."
msgstr "La moitié de la bande passante est recommandée."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1249
msgid "View or change router bandwidth"
msgstr "Consulter ou modifier la bande passante du routeur"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253
msgid "Use open trackers also"
msgstr "Utiliser les open trackers aussi"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1257
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
msgstr "Si coché, les torrents seront annoncés vers les open trackers ainsi que vers les trackers indiqués dans le fichier torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261
msgid "Open tracker announce URLs"
msgstr "URL d'annonce open tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273
msgid "Inbound Settings"
msgstr "Paramètres entrants"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279
msgid "Outbound Settings"
msgstr "Paramètres sortants"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286
msgid "I2CP host"
msgstr "Hôte I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
msgid "I2CP port"
msgstr "Port I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1303
msgid "I2CP options"
msgstr "Options I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1308
msgid "Save configuration"
msgstr "Sauvegarder la configuration"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1325
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "1 saut"
msgstr[1] "{0} sauts"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1326
#, 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
msgid "Size"
msgstr "Taille"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1487
msgid "Priority"
msgstr "Priorité"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1492
msgid "Up to higher level directory"
msgstr "Vers le répertoire parent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517
msgid "Directory"
msgstr "Répertoire"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1522
msgid "Torrent not found?"
msgstr "Torrent non trouvé?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530
msgid "File not found in torrent?"
msgstr "Fichier non trouvé dans le torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1543
msgid "complete"
msgstr "complet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544
msgid "bytes remaining"
msgstr "Octets restants"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1595
msgid "High"
msgstr "Haut"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1600
msgid "Normal"
msgstr "Normal"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1605
msgid "Skip"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1614
msgid "Save priorities"
msgstr "Sauvegarder les priorités"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent envoyé de {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1746
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent déjà actif: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1748
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent déjà dans la queue: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1755
#, fuzzy, java-format
msgid "Failed to copy torrent file to {0}"
msgstr "Impossible de copier le torrent vers {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1759
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Le torrent {0} n'est pas valide"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1764
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Le torrent n'a pas été reçu par {0}"
#~ msgid "size: {0}B"
#~ msgstr "Taille: {0}Octets"
#~ msgid "Estimated Download Time"
#~ msgstr "Temps estimé de téléchargement"
#~ msgid "Torrent file {0} does not exist"
#~ msgstr "Le fichier torrent {0} n'existe pas"
#~ msgid "Copying torrent to {0}"
#~ msgstr "Copie du torrent vers {0}"
#~ msgid "from {0}"
#~ msgstr "depuis {0}"
#~ msgid "Downloading"
#~ msgstr "Téléchargement en cours"
#~ msgid "File"
#~ msgstr "Fichier"
#~ msgid "FileSize"
#~ msgstr "Taille du fichier"
#~ msgid "Download Status"
#~ msgstr "État du téléchargement"
#~ msgid "Details"
#~ msgstr "Détails"
#~ msgid "Depuis l'URL"
#~ msgstr "Quell-URL"
#~ msgid "Directory to store torrents and data"
#~ msgstr "Répertoire de stockage des torrents et des données"
#~ msgid "Cannot change the I2CP settings while torrents are active"
#~ msgstr ""
#~ "On ne peut changer les paramètres I2CP pendant que des torrents sont "
#~ "actifs"
#~ msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
#~ msgstr ""
#~ "Tracker non-i2p dans \"{0}\", suppression de notre liste de trackers!"
#~ msgid "{0} torrents"
#~ msgstr "{0} Torrents"
#~ msgid "Uninteresting"
#~ msgstr "Pas intéressant"
#~ msgid "Choked"
#~ msgstr "Choked"
#~ msgid "Uninterested"
#~ msgstr "Pas interessé"
#~ msgid "Choking"
#~ msgstr "Choking"
#~ msgid "Custom tracker URL"
#~ msgstr "URL tracker spécifique"
#~ msgid "Configure"
#~ msgstr "Configurer"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,864 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2psnark package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
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-31 01:09+0100\n"
"Last-Translator: mixxy <m1xxy@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:94
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "Os torrents serão adicionados em {0} minutos ..."
#: ../java/src/org/klomp/snark/SnarkManager.java:296
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Limite total de subidores mudado a {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:298
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "O limite mínimo de subidores é {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:310
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Largura de banda para a subida foi mudada para {0} kbyte/s."
#: ../java/src/org/klomp/snark/SnarkManager.java:312
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "O limite mínimo da largura de banda para a subida está em {0} kbyte/s."
#: ../java/src/org/klomp/snark/SnarkManager.java:324
#, java-format
msgid "Startup delay limit changed to {0} minutes"
msgstr "Demora do arranque mudado a {0} minutos"
#: ../java/src/org/klomp/snark/SnarkManager.java:371
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr "Mudanças do I2CP e do túnel terão efeito depois de parar todos os torrents"
#: ../java/src/org/klomp/snark/SnarkManager.java:378
msgid "Disconnecting old I2CP destination"
msgstr "Desconectando anterior Destinação I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:382
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "Preferências de I2CP mudadas a {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:386
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "Conectar-se não foi posível com as novas preferências I2CP, utilizarei as anteriores."
#: ../java/src/org/klomp/snark/SnarkManager.java:390
msgid "Unable to reconnect with the old settings!"
msgstr "Impossível se conectar usando as preferências anteriores!"
#: ../java/src/org/klomp/snark/SnarkManager.java:392
msgid "Reconnected on the new I2CP destination"
msgstr "Conectado com a nova Destinação I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:403
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "Conexão I2CP re-estabelecida para \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:414
msgid "Enabled autostart"
msgstr "Ativado o iniciar automáticamente"
#: ../java/src/org/klomp/snark/SnarkManager.java:416
msgid "Disabled autostart"
msgstr "Desativado o iniciar automáticamente"
#: ../java/src/org/klomp/snark/SnarkManager.java:422
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "Uso de rastreadores abertos ativado - Para ter efeito é necesário reiniciar os torrents."
#: ../java/src/org/klomp/snark/SnarkManager.java:424
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "Uso dos rastreadores abertos desativado - Para ter efeito é necesário reiniciar os torrents."
#: ../java/src/org/klomp/snark/SnarkManager.java:431
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "Listado de rastreadores abertos mudado - Para ter efeito é necesário reiniciar os torrents."
#: ../java/src/org/klomp/snark/SnarkManager.java:438
#, java-format
msgid "{0} theme loaded, return to main i2psnark page to view."
msgstr "Tema {0} foi carregado. Volte no menú principal para vê-lo."
#: ../java/src/org/klomp/snark/SnarkManager.java:445
msgid "Configuration unchanged."
msgstr "Configuração não mudada."
#: ../java/src/org/klomp/snark/SnarkManager.java:455
#, java-format
msgid "Unable to save the config to {0}"
msgstr "Não se pode guardar a configuração em {0}."
#: ../java/src/org/klomp/snark/SnarkManager.java:494
msgid "Connecting to I2P"
msgstr "Conectando com I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:497
msgid "Error connecting to I2P - check your I2CP settings!"
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 "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
#, java-format
msgid "Cannot open \"{0}\""
msgstr "Não pode se abrir \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:541
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open trackers only"
msgstr "Aviso - Se ignorará rastreado não I2P no \"{0}\", anunciando só aos rastreadores abertos do I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:543
#, java-format
msgid "Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are disabled, you must enable open trackers before starting the torrent!"
msgstr "Aviso - Se ignorará rastreador não I2P no \"{0}\", rastreadores abertos estão desativados. Tens que ativá-los antes de iniciar o torrent!"
#: ../java/src/org/klomp/snark/SnarkManager.java:563
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "O arquivo .torrent em \"{0}\" não é válido."
#: ../java/src/org/klomp/snark/SnarkManager.java:578
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Torrent adicionado e iniciado: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:580
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Torrent adicionado: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:734
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "Ha arquivos demais no \"{0}\", se apagará ({1}). "
#: ../java/src/org/klomp/snark/SnarkManager.java:736
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "O arquivo de dados do torrent \"{0}\" não pode terminar em \".torrent' e será apagado."
#: ../java/src/org/klomp/snark/SnarkManager.java:738
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "Não ha peças no \"{0}\", se apagará."
#: ../java/src/org/klomp/snark/SnarkManager.java:740
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "Ha peças demais no \"{0}\" e o limite é {1}. Se apagarão."
#: ../java/src/org/klomp/snark/SnarkManager.java:742
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "Peças no \"{0}\" são grandes demais ({1}B). Se apagarão."
#: ../java/src/org/klomp/snark/SnarkManager.java:743
#, java-format
msgid "Limit is {0}B"
msgstr "O limite são \"{0}\"Bytes"
#: ../java/src/org/klomp/snark/SnarkManager.java:751
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Torrents maiores que \"{0}\" Bytes ainda não funcionam, se apagará \"{1}\"."
#: ../java/src/org/klomp/snark/SnarkManager.java:767
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Erro: Não se pode quitar o torrent \"{0}\"."
#: ../java/src/org/klomp/snark/SnarkManager.java:794
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Torrent parado: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:814
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Torrent quitado: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:852
#, java-format
msgid "Download finished: {0}"
msgstr "Finalizada a descarga de \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:880
msgid "Unable to connect to I2P!"
msgstr "Impossível de se conectar com I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:886
#, java-format
msgid "Unable to add {0}"
msgstr "Impossível de adicionar {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:185
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - Cliente de BitTorrent Anônimo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:198
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
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:205
msgid "Refresh page"
msgstr "Atualizar página"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:210
msgid "Forum"
msgstr "Foro"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:264
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1483
msgid "Status"
msgstr "Estado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:272
msgid "Hide Peers"
msgstr "ocultar pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:279
msgid "Show Peers"
msgstr "mostrar pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:286
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464
msgid "Torrent"
msgstr "Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:290
msgid "Estimated time remaining"
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 "Tempo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "Downloaded"
msgstr "Descarregado"
#. 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
msgid "RX"
msgstr "Baixado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:304
msgid "Uploaded"
msgstr "Subido"
#. 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
msgid "TX"
msgstr "Subido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:312
msgid "Down Rate"
msgstr "Taça de descarga"
#. 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
msgid "Rate"
msgstr "Taça"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:322
msgid "Up Rate"
msgstr "Taça de subida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:340
msgid "Stop all torrents and the I2P tunnel"
msgstr "Parar todos os torrents e o túnel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
msgid "Stop All"
msgstr "Parar tudos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:351
msgid "Start all torrents and the I2P tunnel"
msgstr "Iniciar todos os torrents e o túnel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353
msgid "Start All"
msgstr "Arrancar todos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:372
msgid "No torrents loaded."
msgstr "Não carregado nenhum torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
msgid "Totals"
msgstr "Total"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:379
#, 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-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "1 par conectado"
msgstr[1] "{0} pares conectados"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:454
#, java-format
msgid "Fetching {0}"
msgstr "Buscando {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458
msgid "Invalid URL - must start with http://"
msgstr "Endereço não válido - tem que começar com http://"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:489
#, java-format
msgid "Starting up torrent {0}"
msgstr "Iniciando o torrent {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:527
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Apagado o arquivo torrent: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:533
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:543
#, java-format
msgid "Data file deleted: {0}"
msgstr "Apagado o arquivo de dados: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:545
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Não se pode apagar o arquivo de dados: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554
#, java-format
msgid "Data dir deleted: {0}"
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 "Erro ao criar o torrent - Tens que elegir um rastreador."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:602
#, java-format
msgid "Torrent created for \"{0}\""
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 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 "Erro ao criar o torrent \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:610
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
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 "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."
msgstr "Parando todos os torrents e fechando o túnel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:627
msgid "I2P tunnel closed."
msgstr "Túnel I2P fechado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:630
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Abrendo o túnel I2P e iniciando os 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
msgid "Tracker Error"
msgstr "Erro do rastreador"
#: ../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-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "1 par"
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 "semeando"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:784
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1533
msgid "Complete"
msgstr "completo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:792
msgid "OK"
msgstr "bem"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801
msgid "Stalled"
msgstr "estancado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
msgid "No Peers"
msgstr "sem pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
msgid "Stopped"
msgstr "detenido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
#, java-format
msgid "Details at {0} tracker"
msgstr "Detalhes no rastreador {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:838
msgid "Info"
msgstr "Info"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:853
msgid "View files"
msgstr "mostrar arquivos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:855
msgid "Open file"
msgstr "abrir arquivo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:865
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569
msgid "Open"
msgstr "abrir"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:909
msgid "Stop the torrent"
msgstr "Parar o torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:911
msgid "Stop"
msgstr "Parar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:921
msgid "Start the torrent"
msgstr "Iniciar o torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:923
msgid "Start"
msgstr "Iniciar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Retire o torrent da lista ativa, apagando o arquivo .torrent"
#. 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-format
msgid "Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?"
msgstr "Está seguro de que quer apagar o arquivo \\''{0}.torrent\\''? (Dados baixados não se apagarão.)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:941
msgid "Remove"
msgstr "Quitar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:950
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Apagar o arquivo torrent e o(s) arquivo(s) de dados pertenecentes"
#. 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-format
msgid "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?"
msgstr "Está seguro de que quer apagar o arquivo torrent \\''{0}\\'' e todos os dados descarregados deste torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
msgid "Delete"
msgstr "Apagar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:991
msgid "Unknown"
msgstr "desconhecido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
msgid "Seed"
msgstr "Semeador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1019
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "não interessante (O par não tem peças que precisamos.)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1021
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "sufocado (De momento o par não está nos permitindo pedir mais peças.c)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1035
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "desinteressado (Não temos as peças que o par quer.)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1037
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "sufocando (De momento não estamos permitindo que os pares peçam mais peças)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1092
msgid "Add Torrent"
msgstr "Adicionar um torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094
msgid "From URL"
msgstr "URL fonte:"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1097
msgid "Torrent file must originate from an I2P-based tracker"
msgstr "O arquivo torrent tem que incluir um rastreador I2P."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1102
msgid "Add torrent"
msgstr "Adicionar torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr "Também pode copiar arquivos torrent a {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1107
msgid "Removing a .torrent will cause it to stop."
msgstr "A remoção de um arquivo .torrent fará com que ele pare."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1131
msgid "Create Torrent"
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 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 semear (deve estar no caminho especificado)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1140
msgid "Tracker"
msgstr "Rastreador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1142
msgid "Select a tracker"
msgstr "Selecione um rastreador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1155
msgid "or"
msgstr "ou"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1158
msgid "Specify custom tracker announce URL"
msgstr "Especifique o URL de rastreador personalizado"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1161
msgid "Create torrent"
msgstr "Criar torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1180
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1317
msgid "Configuration"
msgstr "Preferências"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1184
msgid "Data directory"
msgstr "Pasta de dados"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1186
msgid "Edit i2psnark.config and restart to change"
msgstr "Para mudar, modifique o arquivo i2psnark.config e re-inície!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190
msgid "Auto start"
msgstr "Iniciar automáticamente"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1194
msgid "If checked, automatically start torrents that are added"
msgstr "se marcado, os torrents adicionados se iniciarão automaticamente"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1198
msgid "Theme"
msgstr "Tema"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1211
msgid "Startup delay"
msgstr "Demora do arranque"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1213
msgid "minutes"
msgstr "minutos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
msgid "Total uploader limit"
msgstr "Limite global de subidores"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240
msgid "peers"
msgstr "pares"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244
msgid "Up bandwidth limit"
msgstr "Limite de largura de banda para a subida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247
msgid "Half available bandwidth recommended."
msgstr "Se recomenda a metade da largura de banda disponível."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1249
msgid "View or change router bandwidth"
msgstr "mostrar e mudar as preferências da largura de banda do roteador"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253
msgid "Use open trackers also"
msgstr "usar também rastreadores abertos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1257
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
msgstr "Se marcado, anunciar os torrents aos rastreadores abertos, assim como aos rastreadores listados no arquivo torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261
msgid "Open tracker announce URLs"
msgstr "URL(s) para anunciar aos rastreadores abertos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273
msgid "Inbound Settings"
msgstr "Preferências de entrada"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279
msgid "Outbound Settings"
msgstr "Preferências de saida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286
msgid "I2CP host"
msgstr "Anfitrião I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
msgid "I2CP port"
msgstr "Porto I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1303
msgid "I2CP options"
msgstr "Opções I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1308
msgid "Save configuration"
msgstr "Guardar configuração"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1325
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "1 salto"
msgstr[1] "{0} saltos"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1326
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "1 túnel"
msgstr[1] "{0} túneles"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1480
msgid "Size"
msgstr "Tamanho"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1487
msgid "Priority"
msgstr "Prioridade"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1492
msgid "Up to higher level directory"
msgstr "Subir uma herarquia"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517
msgid "Directory"
msgstr "Pasta"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1522
msgid "Torrent not found?"
msgstr "Não achei o arquivo torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530
msgid "File not found in torrent?"
msgstr "Arquivo não achado no torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1543
msgid "complete"
msgstr "completo"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544
msgid "bytes remaining"
msgstr "Bytes faltando"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1595
msgid "High"
msgstr "alta"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1600
msgid "Normal"
msgstr "normal"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1605
msgid "Skip"
msgstr "Ignorar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1614
msgid "Save priorities"
msgstr "Guardar prioridades"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent obtido de {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1746
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent já em marcha: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1748
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent já na cola: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1755
#, java-format
msgid "Failed to copy torrent file to {0}"
msgstr "Não se pode copiar o torrent para {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1759
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Torrent em {0} não foi válido"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1764
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Não se pode obter torrent de {0}"
#~ msgid " theme locked and loaded."
#~ msgstr "tema carregado"
#~ msgid "Hide All Attached Peers [connected/total in swarm]"
#~ msgstr "Ocultar todos os pares [conectados/total neste torrent]"
#~ msgid "Show All Attached Peers [connected/total in swarm]"
#~ msgstr "Mostrar todos os pares [conectados/total neste torrent]"
#~ msgid "Loaded Torrents"
#~ msgstr "Torrents carregados"
#~ msgid "Estimated Download Time"
#~ msgstr "tempo restante da descarga"
#~ msgid "1"
#~ msgid_plural "{0}"
#~ msgstr[0] "1"
#~ msgstr[1] "{0}"
#~ msgid "Torrent file {0} does not exist"
#~ msgstr "Arquivo do torrent {0} não existe"
#~ msgid "Copying torrent to {0}"
#~ msgstr "Copiando torrent para {0}"
#~ msgid "from {0}"
#~ msgstr "de {0}"
#~ msgid "Downloading"
#~ msgstr "descarregando"
#~ msgid "File"
#~ msgstr "Arquivo"
#~ msgid "FileSize"
#~ msgstr "Tamanho do arquivo"
#~ msgid "Download Status"
#~ msgstr "Estado"
#, fuzzy
#~ msgid "size: {0}B"
#~ msgstr "Tamaño: {0}Bytes"
#~ msgid "Directory to store torrents and data"
#~ msgstr "Carpeta para guardar los archivos torrent y los datos"
#~ msgid "Do not download"
#~ msgstr "No descargues"
#~ msgid "Details"
#~ msgstr "Detalles"
#~ msgid "Cannot change the I2CP settings while torrents are active"
#~ msgstr ""
#~ "No se puede cammbiar los ajustes I2CP mientras estén activos los torrents"
#~ msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
#~ msgstr ""
#~ "Rastreador fuera de I2P en \"{0}\", borrando de la lista de rastreadores"
#~ msgid "{0} torrents"
#~ msgstr "{0} Torrents"
#~ msgid "Uninteresting"
#~ msgstr "no interesante"
#~ msgid "Choked"
#~ msgstr "frenado"
#~ msgid "Uninterested"
#~ msgstr "desinteresado"
#~ msgid "Choking"
#~ msgstr "frenando"
#~ msgid "Custom tracker URL"
#~ msgstr "URL especial del rastreador"
#~ msgid "Configure"
#~ msgstr "Ajustes"

File diff suppressed because it is too large Load Diff

View File

@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-07-01 04:52+0000\n"
"PO-Revision-Date: 2010-07-01 12:53+0800\n"
"POT-Creation-Date: 2010-10-04 02:45+0000\n"
"PO-Revision-Date: 2010-10-04 12:00+0800\n"
"Last-Translator: walking <walking@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
@@ -224,7 +224,6 @@ msgid "Torrents"
msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:187
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:193
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
msgid "I2PSnark"
msgstr ""
@@ -233,63 +232,65 @@ msgstr ""
msgid "Refresh page"
msgstr "刷新页面"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:193
msgid "<img border=\"0\" src=\"/themes/console/snark/images/arrow_refresh.png\"> I2PSnark"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:195
msgid "Forum"
msgstr "论坛"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:240
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289
msgid "Status"
msgstr "状态"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/status.png\" title=\"Torrent Status\">Status"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/status.png\" title=\"种子状态\">状态"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:246
msgid "Hide Peers"
msgstr "隐藏用户"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/showpeers.png\" title=\"Toggle Peer Visibility\" alt=\"Hide Peers\">"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/showpeers.png\" title=\"隐藏节点\" alt=\"隐藏节点\">"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:249
msgid "Show Peers"
msgstr "显示用户"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/hidepeers.png\" title=\"Toggle Peer Visibility\" alt=\"Show Peers\">"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/hidepeers.png\" title=\"显示节点\" alt=\"显示节点\">"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271
msgid "Torrent"
msgstr "种子"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/torrent.png\" title=\"Loaded Torrents\">Torrent"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/torrent.png\" title=\"载入的种子\">种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:256
msgid "ETA"
msgstr "预计剩余时间"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/eta.png\" title=\"Estimated Download Time\">ETA"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/eta.png\" title=\"预计剩余时间\">预计剩余时间"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:258
msgid "Downloaded"
msgstr "下载"
msgid "<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"Data Downloaded\">RX"
msgstr "<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"下载数据量\">下载"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260
msgid "Uploaded"
msgstr "上传"
msgid "<img border=\"0\" src=\"/themes/console/images/outbound.png\" title=\"Data Uploaded\">TX"
msgstr "<img border=\"0\" src=\"/themes/console/images/outbound.png\" title=\"上传数据量\">上传"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:262
msgid "Down Rate"
msgstr "下载速度"
msgid "<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"Download Speed\">Rate"
msgstr "<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"下载速度\">下载速度"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:264
msgid "Up Rate"
msgstr "上传速度"
msgid "<img border=\"0\" src=\"/themes/console/images/outbound.png\" title=\"Upload Speed\">Rate"
msgstr "<img border=\"0\" src=\"/themes/console/images/outbound.png\" title=\"上传速度\">上传速度"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:271
msgid "Stop all torrents and the I2P tunnel"
msgstr "停止全部种子及I2P隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:273
msgid "Stop All"
msgstr "停止全部"
msgid "<img src=\"/themes/console/snark/images/stop_all.png\" title=\"Stop All Torrents\" alt=\"Stop All\">"
msgstr "<img src=\"/themes/console/snark/images/stop_all.png\" title=\"全部停止\" alt=\"全部停止\">"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:278
msgid "Start all torrents and the I2P tunnel"
msgstr "启动全部种子及I2P隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:280
msgid "Start All"
msgstr "启动全部"
msgid "<img src=\"/themes/console/snark/images/start_all.png\" title=\"Start All Torrents\" alt=\"Start All\">"
msgstr "<img src=\"/themes/console/snark/images/start_all.png\" title=\"全部开始\" alt=\"全部开始\">"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
msgid "No torrents loaded."
@@ -317,13 +318,13 @@ msgid "Torrent file {0} does not exist"
msgstr "种子文件{0}不存在"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1476
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1481
#, java-format
msgid "Torrent already running: {0}"
msgstr "种子已启动:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:348
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1478
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1483
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "种子排队中:{0}"
@@ -450,7 +451,7 @@ msgid "Seeding"
msgstr "正做种"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:682
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1327
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1317
msgid "Complete"
msgstr "完成"
@@ -486,24 +487,24 @@ msgid "Tracker"
msgstr "Tracker服务器"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:751
msgid "Details"
msgstr "详情"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/details.png\">"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785
msgid "Stop the torrent"
msgstr "停止种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:787
msgid "Stop"
msgstr "停止"
msgid "<img src=\"/themes/console/snark/images/stop.png\" title=\"Stop Torrent\" alt=\"Stop\">"
msgstr "<img src=\"/themes/console/snark/images/stop.png\" title=\"停止下载\" alt=\"停止\">"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793
msgid "Start the torrent"
msgstr "启动种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:795
msgid "Start"
msgstr "启动"
msgid "<img src=\"/themes/console/snark/images/start.png\" title=\"Start Torrent\" alt=\"Start\">"
msgstr "<img src=\"/themes/console/snark/images/start.png\" title=\"开始下载\" alt=\"开始\">"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:800
msgid "Remove the torrent from the active list, deleting the .torrent file"
@@ -518,8 +519,8 @@ msgid "Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded
msgstr "您确定要删除文件“{0}.torrent”(下载的数据文件不会被删除)?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:807
msgid "Remove"
msgstr "移除"
msgid "<img src=\"/themes/console/snark/images/remove.png\" title=\"Remove Torrent\" alt=\"Remove\">"
msgstr "<img src=\"/themes/console/snark/images/remove.png\" title=\"删除种子\" alt=\"删除种子\">"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:811
msgid "Delete the .torrent file and the associated data file(s)"
@@ -534,8 +535,8 @@ msgid "Are you sure you want to delete the torrent \\''{0}\\'' and all downloade
msgstr "您确定要删除种子“{0}”(下载的数据文件会一并被删除)?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:818
msgid "Delete"
msgstr "删除"
msgid "<img src=\"/themes/console/snark/images/delete.png\" title=\"Delete Torrent + Data\" alt=\"Delete\">"
msgstr "<img src=\"/themes/console/snark/images/delete.png\" title=\"删除种子 + 数据\" alt=\"删除种子 + 数据\">"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861
msgid "Seed"
@@ -558,8 +559,8 @@ msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "拒绝请求"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:927
msgid "Add Torrent"
msgstr "添加种子"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/add.png\">Add Torrent"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/add.png\">添加种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:929
msgid "From URL"
@@ -571,16 +572,16 @@ msgstr "添加种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:937
#, java-format
msgid "Alternately, you can copy .torrent files to the directory {0}."
msgstr "或者您可以将.torrent文件复制到以下目录{0}."
msgid "You can also copy .torrent files to: <code>{0}"
msgstr "或者您可以将.torrent文件复制到<code>{0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:939
msgid "Removing a .torrent file will cause the torrent to stop."
msgstr "删除种子文件将导致中止该下载任务。"
msgid "Removing a .torrent will cause it to stop."
msgstr "删除种子文件将导致该下载任务中止。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
msgid "Create Torrent"
msgstr "创建种子"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/create.png\">Create Torrent"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/create.png\">创建种子"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:961
@@ -596,8 +597,8 @@ msgid "Select a tracker"
msgstr "选择一个Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "or"
msgstr "或"
msgid "or&nbsp;"
msgstr "或&nbsp;"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:985
msgid "Specify custom tracker announce URL"
@@ -609,8 +610,8 @@ msgstr "创建种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1133
msgid "Configuration"
msgstr "设置"
msgid "<img border=\"0\" src=\"/themes/console/snark/images/config.png\">Configuration"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/config.png\">设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1009
msgid "Data directory"
@@ -709,53 +710,103 @@ msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "{0}隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283
msgid "Up to higher level directory"
msgstr "上一层文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271
msgid "Torrent"
msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288
msgid "File"
msgstr "文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278
msgid "<img border=\"0\" src=\"/themes/console/snark/images/file.png\" title=\"File\" alt=\"File\">&nbsp;"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/file.png\" title=\"文件\" alt=\"文件\">&nbsp;"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288
msgid "Size"
msgstr "大小"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278
msgid "<img border=\"0\" src=\"/themes/console/snark/images/size.png\" title=\"FileSize\" alt=\"FileSize\">Size"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/size.png\" title=\"文件大小\" alt=\"文件大小\">大小"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1311
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279
msgid "<img border=\"0\" src=\"/themes/console/snark/images/status.png\" title=\"Download Status\">Status"
msgstr "<img border=\"0\" src=\"/themes/console/snark/images/status.png\" title=\"下载状态\">状态"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301
msgid "Directory"
msgstr "文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1316
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1306
msgid "Torrent not found?"
msgstr "种子未找到"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1324
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1314
msgid "File not found in torrent?"
msgstr "种子中没有发现文件?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1330
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1320
msgid "complete"
msgstr "完成"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1331
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1321
msgid "bytes remaining"
msgstr "剩余字节数"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1456
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373
msgid "Up to higher level directory"
msgstr "上一层文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1461
#, java-format
msgid "Torrent fetched from {0}"
msgstr "从{0}获取种子成功"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1484
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "{0}的种子中有错误"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1494
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "从{0}获得种子失败"
#~ msgid "Status"
#~ msgstr "状态"
#~ msgid "Hide Peers"
#~ msgstr "隐藏用户"
#~ msgid "Show Peers"
#~ msgstr "显示用户"
#~ msgid "ETA"
#~ msgstr "预计剩余时间"
#~ msgid "Downloaded"
#~ msgstr "已下载"
#~ msgid "Uploaded"
#~ msgstr "已上传"
#~ msgid "Down Rate"
#~ msgstr "下载速度"
#~ msgid "Up Rate"
#~ msgstr "上传速度"
#~ msgid "Stop All"
#~ msgstr "停止全部"
#~ msgid "Start All"
#~ msgstr "启动全部"
#~ msgid "Details"
#~ msgstr "详情"
#~ msgid "Stop"
#~ msgstr "停止"
#~ msgid "Start"
#~ msgstr "启动"
#~ msgid "Remove"
#~ msgstr "移除"
#~ msgid "Delete"
#~ msgstr "删除"
#~ msgid "Add Torrent"
#~ msgstr "添加种子"
#~ msgid "Create Torrent"
#~ msgstr "创建种子"
#~ msgid "or"
#~ msgstr "或"
#~ msgid "Configuration"
#~ msgstr "设置"
#~ msgid "File"
#~ msgstr "文件"
#~ msgid "Size"
#~ msgstr "大小"
#~ msgid "Cannot change the I2CP settings while torrents are active"
#~ msgstr "正在下载/上传无法更改I2CP设置"
#~ msgid "{0} torrents"

View File

@@ -22,4 +22,68 @@
30
</session-timeout>
</session-config>
<!-- mime types not in mime.properties in the jetty 5.1.15 source -->
<mime-mapping>
<extension>mkv</extension>
<mime-type>video/x-matroska</mime-type>
</mime-mapping>
<mime-mapping>
<extension>wmv</extension>
<mime-type>video/x-ms-wmv</mime-type>
</mime-mapping>
<mime-mapping>
<extension>flv</extension>
<mime-type>video/x-flv</mime-type>
</mime-mapping>
<mime-mapping>
<extension>mp4</extension>
<mime-type>video/mp4</mime-type>
</mime-mapping>
<mime-mapping>
<extension>rar</extension>
<mime-type>application/rar</mime-type>
</mime-mapping>
<mime-mapping>
<extension>7z</extension>
<mime-type>application/x-7z-compressed</mime-type>
</mime-mapping>
<mime-mapping>
<extension>iso</extension>
<mime-type>application/x-iso9660-image</mime-type>
</mime-mapping>
<mime-mapping>
<extension>ico</extension>
<mime-type>image/x-icon</mime-type>
</mime-mapping>
<mime-mapping>
<extension>exe</extension>
<mime-type>application/x-msdos-program</mime-type>
</mime-mapping>
<mime-mapping>
<extension>flac</extension>
<mime-type>audio/flac</mime-type>
</mime-mapping>
<mime-mapping>
<extension>m4a</extension>
<mime-type>audio/mpeg</mime-type>
</mime-mapping>
<mime-mapping>
<extension>wma</extension>
<mime-type>audio/x-ms-wma</mime-type>
</mime-mapping>
</web-app>

View File

@@ -3,9 +3,7 @@
<target name="all" depends="clean, build" />
<target name="build" depends="builddep, jar, war" />
<target name="builddep">
<ant dir="../../ministreaming/java/" target="build" />
<ant dir="../../jetty/" target="build" />
<!-- ministreaming will build core -->
<!-- run from top level build.xml to get dependencies built -->
</target>
<condition property="depend.available">
<typefound name="depend" />
@@ -81,7 +79,7 @@
<target name="war" depends="precompilejsp, bundle">
<war destfile="build/i2ptunnel.war" webxml="../jsp/web-out.xml"
basedir="../jsp/" excludes="web.xml, **/*.java, *.jsp">
basedir="../jsp/" excludes="web.xml, web-fragment.xml, web-out.xml, **/*.java, *.jsp">
</war>
</target>

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;
@@ -24,6 +25,9 @@ import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
* This does the transparent gzip decompression on the client side.
* Extended in I2PTunnelHTTPServer to do the compression on the server side.
*
* Simple stream for delivering an HTTP response to
* the client, trivially filtered to make sure "Connection: close"
* is always in the response. Perhaps add transparent handling of the
@@ -33,29 +37,27 @@ import net.i2p.util.Log;
*
*/
class HTTPResponseOutputStream extends FilterOutputStream {
private I2PAppContext _context;
private Log _log;
private ByteCache _cache;
private final I2PAppContext _context;
private final Log _log;
protected ByteArray _headerBuffer;
private boolean _headerWritten;
private byte _buf1[];
private final byte _buf1[];
protected boolean _gzip;
private long _dataWritten;
private InternalGZIPInputStream _in;
private static final int CACHE_SIZE = 8*1024;
private static final ByteCache _cache = ByteCache.getInstance(8, CACHE_SIZE);
// OOM DOS prevention
private static final int MAX_HEADER_SIZE = 64*1024;
public HTTPResponseOutputStream(OutputStream raw) {
super(raw);
_context = I2PAppContext.getGlobalContext();
_context.statManager().createRateStat("i2ptunnel.httpCompressionRatio", "ratio of compressed size to decompressed size after transfer", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpCompressed", "compressed size transferred", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpExpanded", "size transferred after expansion", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpCompressionRatio", "ratio of compressed size to decompressed size after transfer", "I2PTunnel", new long[] { 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpCompressed", "compressed size transferred", "I2PTunnel", new long[] { 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpExpanded", "size transferred after expansion", "I2PTunnel", new long[] { 60*60*1000 });
_log = _context.logManager().getLog(getClass());
_cache = ByteCache.getInstance(8, CACHE_SIZE);
_headerBuffer = _cache.acquire();
_headerWritten = false;
_gzip = false;
_dataWritten = 0;
_buf1 = new byte[1];
}
@@ -96,14 +98,20 @@ class HTTPResponseOutputStream extends FilterOutputStream {
}
}
/** grow (and free) the buffer as necessary */
private void ensureCapacity() {
/**
* grow (and free) the buffer as necessary
* @throws IOException if the headers are too big
*/
private void ensureCapacity() throws IOException {
if (_headerBuffer.getValid() >= MAX_HEADER_SIZE)
throw new IOException("Max header size exceeded: " + MAX_HEADER_SIZE);
if (_headerBuffer.getValid() + 1 >= _headerBuffer.getData().length) {
int newSize = (int)(_headerBuffer.getData().length * 1.5);
ByteArray newBuf = new ByteArray(new byte[newSize]);
System.arraycopy(_headerBuffer.getData(), 0, newBuf.getData(), 0, _headerBuffer.getValid());
newBuf.setValid(_headerBuffer.getValid());
newBuf.setOffset(0);
// if we changed the ByteArray size, don't put it back in the cache
if (_headerBuffer.getData().length == CACHE_SIZE)
_cache.release(_headerBuffer);
_headerBuffer = newBuf;
@@ -172,6 +180,8 @@ class HTTPResponseOutputStream extends FilterOutputStream {
proxyConnectionSent = true;
} else if ( ("Content-encoding".equalsIgnoreCase(key)) && ("x-i2p-gzip".equalsIgnoreCase(val)) ) {
_gzip = true;
} else if ("Proxy-Authenticate".equalsIgnoreCase(key)) {
// filter this hop-by-hop header; outproxy authentication must be configured in I2PTunnelHTTPClient
} else {
out.write((key.trim() + ": " + val.trim() + "\r\n").getBytes());
}
@@ -219,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 decompresser").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;
}
@@ -231,13 +249,13 @@ class HTTPResponseOutputStream extends FilterOutputStream {
_out = out;
}
public void run() {
OutputStream to = null;
_in = null;
long start = System.currentTimeMillis();
long written = 0;
ByteArray ba = null;
try {
_in = new InternalGZIPInputStream(_inRaw);
byte buf[] = new byte[8192];
ba = _cache.acquire();
byte buf[] = ba.getData();
int read = -1;
while ( (read = _in.read(buf)) != -1) {
if (_log.shouldLog(Log.DEBUG))
@@ -251,6 +269,8 @@ class HTTPResponseOutputStream extends FilterOutputStream {
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error decompressing: " + written + ", " + (_in != null ? _in.getTotalRead() + "/" + _in.getTotalExpanded() : ""), ioe);
} catch (OutOfMemoryError oom) {
_log.error("OOM in HTTP Decompressor", oom);
} finally {
if (_log.shouldLog(Log.WARN) && (_in != null))
_log.warn("After decompression, written=" + written +
@@ -259,23 +279,26 @@ class HTTPResponseOutputStream extends FilterOutputStream {
+ ", expanded=" + _in.getTotalExpanded() + ", remaining=" + _in.getRemaining()
+ ", finished=" + _in.getFinished()
: ""));
if (ba != null)
_cache.release(ba);
if (_out != null) try {
_out.close();
} catch (IOException ioe) {}
}
long end = System.currentTimeMillis();
double compressed = (_in != null ? _in.getTotalRead() : 0);
double expanded = (_in != null ? _in.getTotalExpanded() : 0);
double ratio = 0;
if (expanded > 0)
ratio = compressed/expanded;
_context.statManager().addRateData("i2ptunnel.httpCompressionRatio", (int)(100d*ratio), end-start);
_context.statManager().addRateData("i2ptunnel.httpCompressed", (long)compressed, end-start);
_context.statManager().addRateData("i2ptunnel.httpExpanded", (long)expanded, end-start);
if (compressed > 0 && expanded > 0) {
// only update the stats if we did something
double ratio = compressed/expanded;
_context.statManager().addRateData("i2ptunnel.httpCompressionRatio", (int)(100d*ratio), 0);
_context.statManager().addRateData("i2ptunnel.httpCompressed", (long)compressed, 0);
_context.statManager().addRateData("i2ptunnel.httpExpanded", (long)expanded, 0);
}
}
}
/** just a wrapper to provide stats for debugging */
private static class InternalGZIPInputStream extends GZIPInputStream {
public InternalGZIPInputStream(InputStream in) throws IOException {
super(in);
@@ -294,6 +317,12 @@ class HTTPResponseOutputStream extends FilterOutputStream {
return 0;
}
}
/**
* From Inflater javadoc:
* Returns the total number of bytes remaining in the input buffer. This can be used to find out
* what bytes still remain in the input buffer after decompression has finished.
*/
public long getRemaining() {
try {
return super.inf.getRemaining();

View File

@@ -85,8 +85,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
public boolean ownDest = false;
/** the I2CP port */
public String port = System.getProperty(I2PClient.PROP_TCP_PORT, "7654");
/** the I2CP host */
public String host = System.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
/** the listen-on host. Sadly the listen-on port does not have a field. */
public String listenHost = host;
public long readTimeout = -1;
@@ -689,8 +692,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
addtask(task);
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
_log.error(getPrefix() + "Invalid I2PTunnel config to create a client [" + host + ":"+ port + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("clientTaskId", Integer.valueOf(-1));
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
// Otherwise, the tunnel stays up even though the port is down
@@ -763,8 +768,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
addtask(task);
notifyEvent("httpclientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
_log.error(getPrefix() + "Invalid I2PTunnel config to create an httpclient [" + host + ":"+ clientPort + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + clientPort + "]");
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
// Otherwise, the tunnel stays up even though the port is down
@@ -829,7 +836,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, (EventDispatcher) this, this);
addtask(task);
} catch (IllegalArgumentException iae) {
_log.error(getPrefix() + "Invalid I2PTunnel config to create a connect client [" + host + ":"+ _port + "]", iae);
String msg = "Invalid I2PTunnel configuration to create a CONNECT client connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
// Otherwise, the tunnel stays up even though the port is down
// This doesn't work for CLI though... and the tunnel doesn't close itself after error,
@@ -892,8 +902,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
addtask(task);
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
_log.error(getPrefix() + "Invalid I2PTunnel config to create an ircclient [" + host + ":"+ _port + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + _port + "]");
String msg = "Invalid I2PTunnel configuration to create an IRC client connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
// Otherwise, the tunnel stays up even though the port is down
@@ -939,10 +951,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
isShared = "true".equalsIgnoreCase(args[1].trim());
ownDest = !isShared;
I2PTunnelTask task;
task = new I2PSOCKSTunnel(_port, l, ownDest, (EventDispatcher) this, this, null);
addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
try {
I2PTunnelTask task = new I2PSOCKSTunnel(_port, l, ownDest, (EventDispatcher) this, this, null);
addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create a SOCKS Proxy connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
throw iae;
}
} else {
l.log("sockstunnel <port>");
l.log(" creates a tunnel that distributes SOCKS requests.");
@@ -978,10 +998,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
String privateKeyFile = null;
if (args.length == 3)
privateKeyFile = args[2];
I2PTunnelTask task;
task = new I2PSOCKSIRCTunnel(_port, l, ownDest, (EventDispatcher) this, this, privateKeyFile);
addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
try {
I2PTunnelTask task = new I2PSOCKSIRCTunnel(_port, l, ownDest, (EventDispatcher) this, this, privateKeyFile);
addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create a SOCKS IRC Proxy connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
throw iae;
}
} else {
l.log("socksirctunnel <port> [<sharedClient> [<privKeyFile>]]");
l.log(" creates a tunnel for SOCKS IRC.");
@@ -1019,10 +1047,19 @@ public class I2PTunnel implements Logging, EventDispatcher {
if (_port <= 0)
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
StreamrConsumer task = new StreamrConsumer(_host, _port, args[2], l, (EventDispatcher) this, this);
task.startRunning();
addtask(task);
notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId()));
try {
StreamrConsumer task = new StreamrConsumer(_host, _port, args[2], l, (EventDispatcher) this, this);
task.startRunning();
addtask(task);
notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create a Streamr Client connecting to the router at " + host + ':'+ port +
" and sending to " + _host + ':' + port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("streamrtunnnelTaskId", Integer.valueOf(-1));
throw iae;
}
} else {
l.log("streamrclient <host> <port> <destination>");
l.log(" creates a tunnel that receives streaming data.");
@@ -1409,7 +1446,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
for (Iterator it = tasks.iterator(); it.hasNext();) {
I2PTunnelTask t = (I2PTunnelTask) it.next();
int id = t.getId();
_log.debug(getPrefix() + "closetask(): parsing task " + id + " (" + t.toString() + ")");
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "closetask(): parsing task " + id + " (" + t.toString() + ")");
if (id == num) {
closed = closetask(t, forced, l);
break;
@@ -1427,9 +1465,13 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
*/
private boolean closetask(I2PTunnelTask t, boolean forced, Logging l) {
l.log("Closing task " + t.getId() + (forced ? " forced..." : "..."));
if (_log.shouldLog(Log.INFO))
_log.info("Closing task " + t.getId() + (forced ? " forced..." : "..."));
//l.log("Closing task " + t.getId() + (forced ? " forced..." : "..."));
if (t.close(forced)) {
l.log("Task " + t.getId() + " closed.");
if (_log.shouldLog(Log.INFO))
_log.info("Task " + t.getId() + " closed.");
//l.log("Task " + t.getId() + " closed.");
return true;
}
return false;
@@ -1463,6 +1505,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
/**
* Create a new destination, storing the destination and its private keys where
* instructed
* Deprecated - only used by CLI
*
* @param writeTo location to store the private keys
* @param pubDest location to store the destination
@@ -1487,6 +1530,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
/**
* Read in the given destination, display it, and write it to the given location
* Deprecated - only used by CLI
*
* @param readFrom stream to read the destination from
* @param pubDest stream to write the destination to
@@ -1508,6 +1552,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
/**
* Write out the destination to the stream
* Deprecated - only used by CLI
*
* @param d Destination to write
* @param o stream to write the destination to
@@ -1525,6 +1570,10 @@ public class I2PTunnel implements Logging, EventDispatcher {
* also supported, where filename is a file that either contains a
* binary Destination structure or the Base64 encoding of that
* structure.
*
* Since file:<filename> isn't really used, this method is deprecated,
* just call context.namingService.lookup() directly.
* @deprecated Don't use i2ptunnel for lookup! Use I2PAppContext.getGlobalContext().namingService().lookup(name) from i2p.jar
*/
public static Destination destFromName(String name) throws DataFormatException {

View File

@@ -8,7 +8,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
@@ -17,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
@@ -32,7 +29,9 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
public I2PTunnelClient(int localPort, String destinations, Logging l,
boolean ownDest, EventDispatcher notifyThis,
I2PTunnel tunnel, String pkf) throws IllegalArgumentException {
super(localPort, ownDest, l, notifyThis, "SynSender", tunnel, pkf);
super(localPort, ownDest, l, notifyThis,
"Standard client on " + tunnel.listenHost + ':' + localPort,
tunnel, pkf);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openClientResult", "error");
@@ -43,15 +42,11 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
dests = new ArrayList(1);
while (tok.hasMoreTokens()) {
String destination = tok.nextToken();
try {
Destination destN = I2PTunnel.destFromName(destination);
if (destN == null)
l.log("Could not resolve " + destination);
else
dests.add(destN);
} catch (DataFormatException dfe) {
l.log("Bad format parsing \"" + destination + "\"");
}
Destination destN = _context.namingService().lookup(destination);
if (destN == null)
l.log("Could not resolve " + destination);
else
dests.add(destN);
}
if (dests.isEmpty()) {
@@ -110,7 +105,7 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
}
if (size == 1) // skip the rand in the most common case
return dests.get(0);
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
int index = _context.random().nextInt(size);
return dests.get(index);
}
}

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,16 +121,15 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
configurePool(tunnel);
if (open && listenerReady) {
l.log("Ready! Port " + getLocalPort());
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort);
notifyEvent("openBaseClientResult", "ok");
} else {
l.log("Error listening - please see the logs!");
l.log("Client error for " + tunnel.listenHost + ':' + localPort + ", check logs");
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) {
@@ -181,7 +177,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
while (sockMgr == null) {
verifySocketManager();
if (sockMgr == null) {
_log.log(Log.CRIT, "Unable to create socket manager (our own? " + ownDest + ")");
_log.error("Unable to connect to router and build tunnels for " + handlerName);
// FIXME there is a loop in buildSocketManager(), do we really need another one here?
// no matter, buildSocketManager() now throws an IllegalArgumentException
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
}
}
@@ -189,7 +187,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
l.log("Invalid I2CP configuration");
throw new IllegalArgumentException("Socket manager could not be created");
}
l.log("I2P session created");
l.log("Tunnels ready for client: " + handlerName);
} // else delay creating session until createI2PSocket() is called
@@ -208,55 +206,24 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
configurePool(tunnel);
if (open && listenerReady) {
if (openNow)
l.log("Ready! Port " + getLocalPort());
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort);
else
l.log("Listening on port " + getLocalPort() + ", delaying tunnel open until required");
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort + ", delaying tunnel open until required");
notifyEvent("openBaseClientResult", "ok");
} else {
l.log("Error listening - please see the logs!");
l.log("Client error for " + tunnel.listenHost + ':' + localPort + ", check logs");
notifyEvent("openBaseClientResult", "error");
}
}
/**
* 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
*
* We need a socket manager before getDefaultOptions() and most other things
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected void verifySocketManager() {
synchronized(sockLock) {
@@ -289,16 +256,36 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
/** this is ONLY for shared clients */
private static I2PSocketManager socketManager;
/** this is ONLY for shared clients */
/**
* this is ONLY for shared clients
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected synchronized I2PSocketManager getSocketManager() {
return getSocketManager(getTunnel(), this.privKeyFile);
}
/** this is ONLY for shared clients */
/**
* this is ONLY for shared clients
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
return getSocketManager(tunnel, null);
}
/** this is ONLY for shared clients */
/**
* this is ONLY for shared clients
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* 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()) ) {
@@ -319,15 +306,45 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
return socketManager;
}
/**
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected I2PSocketManager buildSocketManager() {
return buildSocketManager(getTunnel(), this.privKeyFile);
return buildSocketManager(getTunnel(), this.privKeyFile, this.l);
}
/**
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
return buildSocketManager(tunnel, null);
}
/** @param pkf absolute path or null */
private static final int RETRY_DELAY = 20*1000;
private static final int MAX_RETRIES = 4;
/**
* @param pkf absolute path or null
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel, String pkf) {
return buildSocketManager(tunnel, pkf, null);
}
/**
* @param pkf absolute path or null
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* 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;
@@ -340,6 +357,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
I2PSocketManager sockManager = null;
// Todo: Can't stop a tunnel from the UI while it's in this loop (no session yet)
int retries = 0;
while (sockManager == null) {
if (pkf != null) {
// Persistent client dest
@@ -348,8 +367,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
fis = new FileInputStream(pkf);
sockManager = I2PSocketManagerFactory.createManager(fis, tunnel.host, portNum, props);
} catch (IOException ioe) {
if (log != null)
log.log("Error opening key file " + ioe);
_log.error("Error opening key file", ioe);
// this is going to loop but if we break we'll get a NPE
throw new IllegalArgumentException("Error opening key file " + ioe);
} finally {
if (fis != null)
try { fis.close(); } catch (IOException ioe) {}
@@ -359,8 +380,22 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
if (sockManager == null) {
_log.log(Log.CRIT, "Unable to create socket manager");
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
// try to make this error sensible as it will happen... sadly we can't get to the listenPort, only the listenHost
String msg = "Unable to connect to the router at " + tunnel.host + ':' + portNum +
" and build tunnels for the client";
if (++retries < MAX_RETRIES) {
if (log != null)
log.log(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
_log.error(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
} else {
if (log != null)
log.log(msg + ", giving up");
_log.log(Log.CRIT, msg + ", giving up");
// not clear if callers can handle null
//return null;
throw new IllegalArgumentException(msg);
}
try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException ie) {}
}
}
sockManager.setName("Client");
@@ -469,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);
@@ -479,7 +513,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
localPort = ss.getLocalPort();
}
notifyEvent("clientLocalPort", new Integer(ss.getLocalPort()));
l.log("Listening for clients on port " + localPort + " of " + getTunnel().listenHost);
// duplicates message in constructor
//l.log("Listening for clients on port " + localPort + " of " + getTunnel().listenHost);
// Notify constructor that port is ready
synchronized (this) {
@@ -497,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) {
@@ -517,9 +549,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
notifyAll();
}
}
synchronized (_waitingSockets) {
_waitingSockets.notifyAll();
}
}
/**
@@ -529,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;
@@ -556,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);
@@ -608,7 +625,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
} // else the app chaining to this one closes it!
}
l.log("Closing client " + toString());
l.log("Stopping client " + toString());
open = false;
try {
if (ss != null) ss.close();
@@ -616,10 +633,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
ex.printStackTrace();
return false;
}
l.log("Client closed.");
//l.log("Client closed.");
}
synchronized (_waitingSockets) { _waitingSockets.notifyAll(); }
return true;
}
@@ -627,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

@@ -18,6 +18,7 @@ import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
@@ -26,6 +27,7 @@ import net.i2p.util.Log;
/**
* Supports the following:
*<pre>
* (where protocol is generally HTTP/1.1 but is ignored)
* (where host is one of:
* example.i2p
@@ -39,23 +41,23 @@ import net.i2p.util.Log;
* CONNECT host protocol
* CONNECT host:port
* CONNECT host:port protocol (this is the standard)
*</pre>
*
* Additional lines after the CONNECT line but before the blank line are ignored and stripped.
* The CONNECT line is removed for .i2p accesses
* but passed along for outproxy accesses.
*
* Ref:
*<pre>
* INTERNET-DRAFT Ari Luotonen
* Expires: September 26, 1997 Netscape Communications Corporation
* <draft-luotonen-ssl-tunneling-03.txt> March 26, 1997
* Tunneling SSL Through a WWW Proxy
*</pre>
*
* @author zzz a stripped-down I2PTunnelHTTPClient
*/
public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelConnectClient.class);
private final List<String> _proxyList;
public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements Runnable {
private final static byte[] ERR_DESTINATION_UNKNOWN =
("HTTP/1.1 503 Service Unavailable\r\n"+
@@ -69,16 +71,6 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
"Could not find the following Destination:<BR><BR><div>")
.getBytes();
private final static byte[] ERR_NO_OUTPROXY =
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"\r\n"+
"<html><body><H1>I2P ERROR: No outproxy found</H1>"+
"Your request was for a site outside of I2P, but you have no "+
"HTTP outproxy configured. Please configure an outproxy in I2PTunnel")
.getBytes();
private final static byte[] ERR_BAD_PROTOCOL =
("HTTP/1.1 405 Bad Method\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@@ -98,17 +90,23 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
"Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.<BR>")
.getBytes();
private final static byte[] ERR_AUTH =
("HTTP/1.1 407 Proxy Authentication Required\r\n"+
"Content-Type: text/html; charset=UTF-8\r\n"+
"Cache-control: no-cache\r\n"+
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.5\r\n" + // try to get a UTF-8-encoded response back for the password
"Proxy-Authenticate: Basic realm=\"I2P SSL Proxy\"\r\n" +
"\r\n"+
"<html><body><H1>I2P ERROR: PROXY AUTHENTICATION REQUIRED</H1>"+
"This proxy is configured to require authentication.<BR>")
.getBytes();
private final static byte[] SUCCESS_RESPONSE =
("HTTP/1.1 200 Connection Established\r\n"+
"Proxy-agent: I2P\r\n"+
"\r\n")
.getBytes();
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
private static final File _errorDir = new File(I2PAppContext.getGlobalContext().getBaseDir(), "docs");
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router
@@ -116,9 +114,8 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
public I2PTunnelConnectClient(int localPort, Logging l, boolean ownDest,
String wwwProxy, EventDispatcher notifyThis,
I2PTunnel tunnel) throws IllegalArgumentException {
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
super(localPort, ownDest, l, notifyThis, "HTTPS Proxy on " + tunnel.listenHost + ':' + localPort + " #" + (++__clientId), tunnel);
_proxyList = new ArrayList();
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openConnectClientResult", "error");
return;
@@ -130,25 +127,11 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
_proxyList.add(tok.nextToken().trim());
}
setName(getLocalPort() + " -> ConnectClient [Outproxy list: " + wwwProxy + "]");
setName("HTTPS Proxy on " + tunnel.listenHost + ':' + localPort);
startRunning();
}
private String getPrefix(long requestId) { return "Client[" + _clientId + "/" + requestId + "]: "; }
private String selectProxy() {
synchronized (_proxyList) {
int size = _proxyList.size();
if (size <= 0)
return null;
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
return _proxyList.get(index);
}
}
private static final int DEFAULT_READ_TIMEOUT = 60*1000;
/**
* create the default options (using the default timeout, etc)
*
@@ -168,7 +151,6 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
return opts;
}
private static long __requestId = 0;
protected void clientConnectionRun(Socket s) {
InputStream in = null;
OutputStream out = null;
@@ -182,6 +164,7 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
String line, method = null, host = null, destination = null, restofline = null;
StringBuilder newRequest = new StringBuilder();
int ahelper = 0;
String authorization = null;
while (true) {
// Use this rather than BufferedReader because we can't have readahead,
// since we are passing the stream on to I2PTunnelRunner
@@ -222,7 +205,7 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
}
destination = currentProxy;
usingWWWProxy = true;
newRequest.append("CONNECT ").append(host).append(restofline).append("\r\n\r\n"); // HTTP spec
newRequest.append("CONNECT ").append(host).append(restofline).append("\r\n"); // HTTP spec
} else if (host.toLowerCase().equals("localhost")) {
writeErrorMessage(ERR_LOCALHOST, out);
s.close();
@@ -238,7 +221,11 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
_log.debug(getPrefix(requestId) + "REST :" + restofline + ":");
_log.debug(getPrefix(requestId) + "DEST :" + destination + ":");
}
} else if (line.toLowerCase().startsWith("proxy-authorization: basic ")) {
// strip Proxy-Authenticate from the response in HTTPResponseOutputStream
// save for auth check below
authorization = line.substring(27); // "proxy-authorization: basic ".length()
line = null;
} else if (line.length() > 0) {
// Additional lines - shouldn't be too many. Firefox sends:
// User-Agent: blabla
@@ -249,6 +236,23 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
// but for now just chomp them all.
line = null;
} else {
// Add Proxy-Authentication header for next hop (outproxy)
if (usingWWWProxy && Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_AUTH)).booleanValue()) {
// specific for this proxy
String user = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_USER_PREFIX + currentProxy);
String pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW_PREFIX + currentProxy);
if (user == null || pw == null) {
// if not, look at default user and pw
user = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_USER);
pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW);
}
if (user != null && pw != null) {
newRequest.append("Proxy-Authorization: Basic ")
.append(Base64.encode((user + ':' + pw).getBytes(), true)) // true = use standard alphabet
.append("\r\n");
}
}
newRequest.append("\r\n"); // HTTP spec
// do it
break;
}
@@ -260,7 +264,20 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
return;
}
Destination clientDest = I2PTunnel.destFromName(destination);
// Authorization
if (!authorize(s, requestId, authorization)) {
if (_log.shouldLog(Log.WARN)) {
if (authorization != null)
_log.warn(getPrefix(requestId) + "Auth failed, sending 407 again");
else
_log.warn(getPrefix(requestId) + "Auth required, sending 407");
}
writeErrorMessage(ERR_AUTH, out);
s.close();
return;
}
Destination clientDest = _context.namingService().lookup(destination);
if (clientDest == null) {
String str;
byte[] header;
@@ -322,8 +339,8 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
_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

@@ -27,7 +27,7 @@ import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Base32;
import net.i2p.data.DataFormatException;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
@@ -60,10 +60,7 @@ import net.i2p.util.Translate;
* and POST have been tested, though other $methods should work.
*
*/
public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelHTTPClient.class);
protected final List proxyList = new ArrayList();
public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runnable {
private HashMap addressHelpers = new HashMap();
@@ -152,16 +149,22 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.<BR>")
.getBytes();
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
private static final File _errorDir = new File(I2PAppContext.getGlobalContext().getBaseDir(), "docs");
private final static byte[] ERR_AUTH =
("HTTP/1.1 407 Proxy Authentication Required\r\n"+
"Content-Type: text/html; charset=UTF-8\r\n"+
"Cache-control: no-cache\r\n"+
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.5\r\n" + // try to get a UTF-8-encoded response back for the password
"Proxy-Authenticate: Basic realm=\"I2P HTTP Proxy\"\r\n" +
"\r\n"+
"<html><body><H1>I2P ERROR: PROXY AUTHENTICATION REQUIRED</H1>"+
"This proxy is configured to require authentication.<BR>")
.getBytes();
public I2PTunnelHTTPClient(int localPort, Logging l, I2PSocketManager sockMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) {
super(localPort, l, sockMgr, tunnel, notifyThis, clientId);
// proxyList = new ArrayList();
setName(getLocalPort() + " -> HTTPClient [NO PROXIES]");
setName("HTTP Proxy on " + getTunnel().listenHost + ':' + localPort);
startRunning();
notifyEvent("openHTTPClientResult", "ok");
@@ -173,7 +176,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest,
String wwwProxy, EventDispatcher notifyThis,
I2PTunnel tunnel) throws IllegalArgumentException {
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
super(localPort, ownDest, l, notifyThis, "HTTP Proxy on " + tunnel.listenHost + ':' + localPort + " #" + (++__clientId), tunnel);
//proxyList = new ArrayList(); // We won't use outside of i2p
if (waitEventValue("openBaseClientResult").equals("error")) {
@@ -184,35 +187,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (wwwProxy != null) {
StringTokenizer tok = new StringTokenizer(wwwProxy, ", ");
while (tok.hasMoreTokens())
proxyList.add(tok.nextToken().trim());
_proxyList.add(tok.nextToken().trim());
}
setName(getLocalPort() + " -> HTTPClient [WWW outproxy list: " + wwwProxy + "]");
setName("HTTP Proxy on " + tunnel.listenHost + ':' + localPort);
startRunning();
notifyEvent("openHTTPClientResult", "ok");
}
private String getPrefix(long requestId) { return "Client[" + _clientId + "/" + requestId + "]: "; }
private String selectProxy() {
synchronized (proxyList) {
int size = proxyList.size();
if (size <= 0) {
if (_log.shouldLog(Log.INFO))
_log.info("Proxy list is empty - no outproxy available");
l.log("Proxy list is empty - no outproxy available");
return null;
}
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
String proxy = (String)proxyList.get(index);
return proxy;
}
}
private static final int DEFAULT_READ_TIMEOUT = 60*1000;
/**
* create the default options (using the default timeout, etc)
* unused?
@@ -281,7 +265,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
public static final String PROP_VIA = "i2ptunnel.httpclient.sendVia";
public static final String PROP_JUMP_SERVERS = "i2ptunnel.httpclient.jumpServers";
private static long __requestId = 0;
protected void clientConnectionRun(Socket s) {
InputStream in = null;
OutputStream out = null;
@@ -296,6 +279,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
String line, method = null, protocol = null, host = null, destination = null;
StringBuilder newRequest = new StringBuilder();
int ahelper = 0;
String authorization = null;
while ((line = reader.readLine(method)) != null) {
line = line.trim();
if (_log.shouldLog(Log.DEBUG))
@@ -445,11 +429,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
// Host resolvable from database, verify addresshelper key
// Silently bypass correct keys, otherwise alert
String destB64 = null;
try {
Destination _dest = I2PTunnel.destFromName(host);
if (_dest != null)
destB64 = _dest.toBase64();
} catch (DataFormatException dfe) {}
Destination _dest = _context.namingService().lookup(host);
if (_dest != null)
destB64 = _dest.toBase64();
if (destB64 != null && !destB64.equals(ahelperKey))
{
// Conflict: handle when URL reconstruction done
@@ -626,11 +608,25 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
//line = "From: i2p";
line = null;
continue; // completely strip the line
} else if (lowercaseLine.startsWith("authorization: ntlm ")) {
// Block Windows NTLM after 401
line = null;
continue;
} else if (lowercaseLine.startsWith("proxy-authorization: ")) {
// This should be for us. It is a
// hop-by-hop header, and we definitely want to block Windows NTLM after a far-end 407.
// Response to far-end shouldn't happen, as we
// strip Proxy-Authenticate from the response in HTTPResponseOutputStream
if (lowercaseLine.startsWith("proxy-authorization: basic "))
// save for auth check below
authorization = line.substring(27); // "proxy-authorization: basic ".length()
line = null;
continue;
}
}
if (line.length() == 0) {
// No more headers, add our own and break out of the loop
String ok = getTunnel().getClientOptions().getProperty("i2ptunnel.gzip");
boolean gzip = DEFAULT_GZIP;
if (ok != null)
@@ -649,6 +645,22 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
else
newRequest.append("User-Agent: MYOB/6.66 (AN/ON)\r\n");
}
// Add Proxy-Authentication header for next hop (outproxy)
if (usingWWWProxy && Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_AUTH)).booleanValue()) {
// specific for this proxy
String user = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_USER_PREFIX + currentProxy);
String pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW_PREFIX + currentProxy);
if (user == null || pw == null) {
// if not, look at default user and pw
user = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_USER);
pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW);
}
if (user != null && pw != null) {
newRequest.append("Proxy-Authorization: Basic ")
.append(Base64.encode((user + ':' + pw).getBytes(), true)) // true = use standard alphabet
.append("\r\n");
}
}
newRequest.append("Connection: close\r\n\r\n");
break;
} else {
@@ -677,12 +689,26 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
// Serve local proxy files (images, css linked from error pages)
// Ignore all the headers
// Allow without authorization
if (usingInternalServer) {
serveLocalFile(out, method, targetRequest);
s.close();
return;
}
// Authorization
if (!authorize(s, requestId, authorization)) {
if (_log.shouldLog(Log.WARN)) {
if (authorization != null)
_log.warn(getPrefix(requestId) + "Auth failed, sending 407 again");
else
_log.warn(getPrefix(requestId) + "Auth required, sending 407");
}
out.write(getErrorPage("auth", ERR_AUTH));
s.close();
return;
}
// If the host is "i2p", the getHostName() lookup failed, don't try to
// look it up again as the naming service does not do negative caching
// so it will be slow.
@@ -691,7 +717,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if ("i2p".equals(host))
clientDest = null;
else
clientDest = I2PTunnel.destFromName(destination);
clientDest = _context.namingService().lookup(destination);
if (clientDest == null) {
//l.log("Could not resolve " + destination + ".");
@@ -784,17 +810,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
* @return b32hash.b32.i2p, or "i2p" on lookup failure.
* Prior to 0.7.12, returned b64 key
*/
private final static String getHostName(String host) {
private final String getHostName(String host) {
if (host == null) return null;
if (host.length() == 60 && host.toLowerCase().endsWith(".b32.i2p"))
return host;
try {
Destination dest = I2PTunnel.destFromName(host);
if (dest == null) return "i2p";
return Base32.encode(dest.calculateHash().getData()) + ".b32.i2p";
} catch (DataFormatException dfe) {
return "i2p";
}
Destination dest = _context.namingService().lookup(host);
if (dest == null) return "i2p";
return Base32.encode(dest.calculateHash().getData()) + ".b32.i2p";
}
/**
@@ -808,7 +830,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
* @return non-null
*/
private byte[] getErrorPage(String base, byte[] backup) {
return getErrorPage(getTunnel().getContext(), base, backup);
return getErrorPage(_context, base, backup);
}
private static byte[] getErrorPage(I2PAppContext ctx, String base, byte[] backup) {
@@ -871,15 +893,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
_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/";
@@ -917,11 +939,11 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
// Skip jump servers we don't know
String jumphost = jurl.substring(7); // "http://"
jumphost = jumphost.substring(0, jumphost.indexOf('/'));
try {
Destination dest = I2PTunnel.destFromName(jumphost);
if (dest == null) continue;
} catch (DataFormatException dfe) {
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());
@@ -984,7 +1006,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (!found) {
try {
Destination d = I2PTunnel.destFromName(host);
Destination d = _context.namingService().lookup(host);
if (d == null) return false;
} catch (DataFormatException dfe) {
}

View File

@@ -0,0 +1,151 @@
/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java)
* (c) 2003 - 2004 mihi
*/
package net.i2p.i2ptunnel;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.ArrayList;
import java.io.File;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Base64;
import net.i2p.util.EventDispatcher;
import net.i2p.util.InternalSocket;
import net.i2p.util.Log;
/**
* Common things for HTTPClient and ConnectClient
* Retrofit over them in 0.8.2
*
* @since 0.8.2
*/
public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implements Runnable {
protected final List<String> _proxyList;
protected final static byte[] ERR_NO_OUTPROXY =
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"\r\n"+
"<html><body><H1>I2P ERROR: No outproxy found</H1>"+
"Your request was for a site outside of I2P, but you have no "+
"HTTP outproxy configured. Please configure an outproxy in I2PTunnel")
.getBytes();
/** used to assign unique IDs to the threads / clients. no logic or functionality */
protected static volatile long __clientId = 0;
protected static final File _errorDir = new File(I2PAppContext.getGlobalContext().getBaseDir(), "docs");
protected String getPrefix(long requestId) { return "Client[" + _clientId + "/" + requestId + "]: "; }
protected String selectProxy() {
synchronized (_proxyList) {
int size = _proxyList.size();
if (size <= 0)
return null;
int index = _context.random().nextInt(size);
return _proxyList.get(index);
}
}
protected static final int DEFAULT_READ_TIMEOUT = 60*1000;
protected static long __requestId = 0;
public I2PTunnelHTTPClientBase(int localPort, boolean ownDest, Logging l,
EventDispatcher notifyThis, String handlerName,
I2PTunnel tunnel) throws IllegalArgumentException {
super(localPort, ownDest, l, notifyThis, handlerName, tunnel);
_proxyList = new ArrayList(4);
}
public I2PTunnelHTTPClientBase(int localPort, Logging l, I2PSocketManager sktMgr,
I2PTunnel tunnel, EventDispatcher notifyThis, long clientId )
throws IllegalArgumentException {
super(localPort, l, sktMgr, tunnel, notifyThis, clientId);
_proxyList = new ArrayList(4);
}
/** all auth @since 0.8.2 */
public static final String PROP_AUTH = "proxyAuth";
public static final String PROP_USER = "proxyUsername";
public static final String PROP_PW = "proxyPassword";
/** additional users may be added with proxyPassword.user=pw */
public static final String PROP_PW_PREFIX = PROP_PW + '.';
public static final String PROP_OUTPROXY_AUTH = "outproxyAuth";
public static final String PROP_OUTPROXY_USER = "outproxyUsername";
public static final String PROP_OUTPROXY_PW = "outproxyPassword";
/** passwords for specific outproxies may be added with outproxyUsername.fooproxy.i2p=user and outproxyPassword.fooproxy.i2p=pw */
public static final String PROP_OUTPROXY_USER_PREFIX = PROP_OUTPROXY_USER + '.';
public static final String PROP_OUTPROXY_PW_PREFIX = PROP_OUTPROXY_PW + '.';
/**
* @param authorization may be null
* @return success
*/
protected boolean authorize(Socket s, long requestId, String authorization) {
// Authorization
// Ref: RFC 2617
// If the socket is an InternalSocket, no auth required.
String authRequired = getTunnel().getClientOptions().getProperty(PROP_AUTH);
if (authRequired != null && (authRequired.equalsIgnoreCase("true") || authRequired.equalsIgnoreCase("basic"))) {
if (s instanceof InternalSocket) {
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix(requestId) + "Internal access, no auth required");
return true;
} else if (authorization != null) {
// hmm safeDecode(foo, true) to use standard alphabet is private in Base64
byte[] decoded = Base64.decode(authorization.replace("/", "~").replace("+", "="));
if (decoded != null) {
// We send Accept-Charset: UTF-8 in the 407 so hopefully it comes back that way inside the B64 ?
try {
String dec = new String(decoded, "UTF-8");
String[] parts = dec.split(":");
String user = parts[0];
String pw = parts[1];
// first try pw for that user
String configPW = getTunnel().getClientOptions().getProperty(PROP_PW_PREFIX + user);
if (configPW == null) {
// if not, look at default user and pw
String configUser = getTunnel().getClientOptions().getProperty(PROP_USER);
if (user.equals(configUser))
configPW = getTunnel().getClientOptions().getProperty(PROP_PW);
}
if (configPW != null) {
if (pw.equals(configPW)) {
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix(requestId) + "Good auth - user: " + user + " pw: " + pw);
return true;
} else {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Bad auth, pw mismatch - user: " + user + " pw: " + pw + " expected: " + configPW);
}
} else {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Bad auth, no stored pw for user: " + user + " pw: " + pw);
}
} catch (UnsupportedEncodingException uee) {
_log.error(getPrefix(requestId) + "No UTF-8 support? B64: " + authorization, uee);
} catch (ArrayIndexOutOfBoundsException aioobe) {
// no ':' in response
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Bad auth B64: " + authorization, aioobe);
}
} else {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Bad auth B64: " + authorization);
}
}
return false;
} else {
return true;
}
}
}

View File

@@ -15,6 +15,7 @@ import java.util.Properties;
import java.util.zip.GZIPOutputStream;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PAppThread;
@@ -30,12 +31,29 @@ 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";
private static final String DEST64_HEADER = "X-I2P-DestB64";
private static final String DEST32_HEADER = "X-I2P-DestB32";
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);
@@ -69,13 +87,15 @@ 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();
StringBuilder command = new StringBuilder(128);
Properties headers = readHeaders(in, command);
Properties headers = readHeaders(in, command,
CLIENT_SKIPHEADERS, getTunnel().getContext());
headers.setProperty(HASH_HEADER, socket.getPeerDestination().calculateHash().toBase64());
headers.setProperty(DEST32_HEADER, Base32.encode(socket.getPeerDestination().calculateHash().getData()) + ".b32.i2p" );
headers.setProperty(DEST64_HEADER, socket.getPeerDestination().toBase64());
@@ -118,18 +138,31 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
useGZIP = true;
if (allowGZIP && useGZIP) {
I2PAppThread req = new I2PAppThread(new CompressedRequestor(s, socket, modifiedHeader), Thread.currentThread().getName()+".hc");
I2PAppThread req = new I2PAppThread(
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();
@@ -143,23 +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;
public CompressedRequestor(Socket webserver, I2PSocket browser, String headers) {
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");
@@ -174,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();
@@ -192,12 +226,20 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
// at java.lang.Thread.run(Thread.java:619)
// at net.i2p.util.I2PThread.run(I2PThread.java:71)
try {
serverin = _webserver.getInputStream();
serverin = _webserver.getInputStream();
} catch (NullPointerException npe) {
throw new IOException("getInputStream NPE");
}
CompressedResponseOutputStream compressedOut = new CompressedResponseOutputStream(browserout);
Sender s = new Sender(compressedOut, serverin, "server: server to browser");
//Change headers to protect server identity
StringBuilder command = new StringBuilder(128);
Properties headers = readHeaders(serverin, command,
SERVER_SKIPHEADERS, _ctx);
String modifiedHeaders = formatHeaders(headers, command);
compressedOut.write(modifiedHeaders.getBytes());
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
@@ -216,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");
@@ -260,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;
@@ -290,6 +337,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
}
/** just a wrapper to provide stats for debugging */
private static class InternalGZIPOutputStream extends GZIPOutputStream {
public InternalGZIPOutputStream(OutputStream target) throws IOException {
super(target);
@@ -327,16 +375,17 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
/** ridiculously long, just to prevent OOM DOS @since 0.7.13 */
private static final int MAX_HEADERS = 60;
private Properties readHeaders(InputStream in, StringBuilder command) throws IOException {
private static Properties readHeaders(InputStream in, StringBuilder command, String[] skipHeaders, I2PAppContext ctx) throws IOException {
Properties headers = new Properties();
StringBuilder buf = new StringBuilder(128);
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;
if (command.length() > 0) {
for (int i = 0; i < command.length(); i++) {
@@ -348,7 +397,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
}
if (trimmed > 0)
getTunnel().getContext().statManager().addRateData("i2ptunnel.httpNullWorkaround", trimmed, 0);
ctx.statManager().addRateData("i2ptunnel.httpNullWorkaround", trimmed, 0);
int i = 0;
while (true) {
@@ -370,19 +419,28 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
value = buf.substring(split+1).trim(); // ":"
else
value = "";
if ("Accept-encoding".equalsIgnoreCase(name))
name = "Accept-encoding";
else if ("X-Accept-encoding".equalsIgnoreCase(name))
name = "X-Accept-encoding";
else if (HASH_HEADER.equalsIgnoreCase(name))
continue; // Prevent spoofing
else if (DEST64_HEADER.equalsIgnoreCase(name))
continue; // Prevent spoofing
else if (DEST32_HEADER.equalsIgnoreCase(name))
continue; // Prevent spoofing
// For incoming, we remove certain headers to prevent spoofing.
// For outgoing, we remove certain headers to improve anonymity.
boolean skip = false;
for (String skipHeader: skipHeaders) {
if (skipHeader.equalsIgnoreCase(name)) {
skip = true;
break;
}
}
if(skip) {
continue;
}
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

@@ -9,9 +9,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PAppThread;
@@ -22,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;
@@ -47,21 +43,17 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
ownDest,
l,
notifyThis,
"IRCHandler " + (++__clientId), tunnel, pkf);
"IRC Client on " + tunnel.listenHost + ':' + localPort + " #" + (++__clientId), tunnel, pkf);
StringTokenizer tok = new StringTokenizer(destinations, ", ");
dests = new ArrayList(2);
while (tok.hasMoreTokens()) {
String destination = tok.nextToken();
try {
Destination destN = I2PTunnel.destFromName(destination);
if (destN == null)
l.log("Could not resolve " + destination);
else
dests.add(destN);
} catch (DataFormatException dfe) {
l.log("Bad format parsing \"" + destination + "\"");
}
Destination destN = _context.namingService().lookup(destination);
if (destN == null)
l.log("Could not resolve " + destination);
else
dests.add(destN);
}
if (dests.isEmpty()) {
@@ -81,7 +73,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
//return;
}
setName(getLocalPort() + " -> IRCClient");
setName("IRC Client on " + tunnel.listenHost + ':' + localPort);
startRunning();
@@ -124,7 +116,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
}
if (size == 1) // skip the rand in the most common case
return dests.get(0);
int index = I2PAppContext.getGlobalContext().random().nextInt(size);
int index = _context.random().nextInt(size);
return dests.get(index);
}
@@ -136,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;
@@ -182,6 +176,8 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
}
outmsg=outmsg+"\r\n"; // rfc1459 sec. 2.3
output.write(outmsg.getBytes("ISO-8859-1"));
// probably doesn't do much but can't hurt
output.flush();
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("inbound BLOCKED: "+inmsg);
@@ -211,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;
@@ -257,6 +255,8 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
}
outmsg=outmsg+"\r\n"; // rfc1459 sec. 2.3
output.write(outmsg.getBytes("ISO-8859-1"));
// save 250 ms in streaming
output.flush();
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("outbound BLOCKED: "+"\""+inmsg+"\"");
@@ -310,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;
}
@@ -433,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

@@ -127,7 +127,16 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
// this does not increment totalSent
i2pout.write(initialI2PData);
// do NOT flush here, it will block and then onTimeout.run() won't happen on fail.
//i2pout.flush();
// But if we don't flush, then we have to wait for the connectDelay timer to fire
// in i2p socket? To be researched and/or fixed.
//
// AS OF 0.8.1, MessageOutputStream.flush() is fixed to only wait for accept,
// not for "completion" (i.e. an ACK from the far end).
// So we now get a fast return from flush(), and can do it here to save 250 ms.
// To make sure we are under the initial window size and don't hang waiting for accept,
// only flush if it fits in one message.
if (initialI2PData.length <= 1730) // ConnectionOptions.DEFAULT_MAX_MESSAGE_SIZE
i2pout.flush();
}
}
if (initialSocketData != null) {

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;
@@ -61,17 +71,25 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
private int DEFAULT_LOCALPORT = 4488;
protected int localPort = DEFAULT_LOCALPORT;
/**
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privData, notifyThis, 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);
}
/**
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
SetUsePool(tunnel);
super("Server at " + host + ':' + port, notifyThis, tunnel);
_log = tunnel.getContext().logManager().getLog(getClass());
FileInputStream fis = null;
try {
fis = new FileInputStream(privkey);
@@ -85,21 +103,23 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
}
/**
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
SetUsePool(tunnel);
super("Server at " + host + ':' + port, notifyThis, tunnel);
_log = tunnel.getContext().logManager().getLog(getClass());
init(host, port, privData, privkeyname, l);
}
private static final int RETRY_DELAY = 20*1000;
private static final int MAX_RETRIES = 4;
private void SetUsePool(I2PTunnel Tunnel) {
String usePool = Tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
}
/**
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
private void init(InetAddress host, int port, InputStream privData, String privkeyname, Logging l) {
this.l = l;
this.remoteHost = host;
@@ -111,7 +131,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
try {
portNum = Integer.parseInt(getTunnel().port);
} catch (NumberFormatException nfe) {
_log.log(Log.CRIT, "Invalid port specified [" + getTunnel().port + "], reverting to " + portNum);
_log.error("Invalid port specified [" + getTunnel().port + "], reverting to " + portNum);
}
}
@@ -124,7 +144,18 @@ 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) {
synchronized (slock) {
sockMgr = I2PSocketManagerFactory.createManager(privDataCopy, getTunnel().host, portNum,
@@ -132,15 +163,25 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
if (sockMgr == null) {
_log.log(Log.CRIT, "Unable to create socket manager");
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
// try to make this error sensible as it will happen...
String msg = "Unable to connect to the router at " + getTunnel().host + ':' + portNum +
" and build tunnels for the server at " + getTunnel().listenHost + ':' + port;
if (++retries < MAX_RETRIES) {
this.l.log(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
_log.error(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds");
} else {
this.l.log(msg + ", giving up");
_log.log(Log.CRIT, msg + ", giving up");
throw new IllegalArgumentException(msg);
}
try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException ie) {}
privDataCopy.reset();
}
}
sockMgr.setName("Server");
getTunnel().addSession(sockMgr.getSession());
l.log("Ready!");
l.log("Tunnels ready for server at " + getTunnel().listenHost + ':' + port);
notifyEvent("openServerResult", "ok");
open = true;
}
@@ -169,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();
}
@@ -206,7 +246,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
return false;
}
l.log("Shutting down server " + toString());
l.log("Stopping tunnels for server at " + this.remoteHost + ':' + this.remotePort);
try {
if (i2pss != null) i2pss.close();
getTunnel().removeSession(sockMgr.getSession());
@@ -215,7 +255,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
_log.error("Error destroying the session", ex);
//System.exit(1);
}
l.log("Server shut down.");
//l.log("Server shut down.");
open = false;
return true;
}
@@ -229,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);
}
}
@@ -305,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

@@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Destination;
@@ -200,7 +201,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
@Override
public void run() {
try {
Destination dest = I2PTunnel.destFromName(destination);
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(destination);
if (dest == null) {
synchronized (lock) { // Logger is not thread safe
l.log("Unresolvable: " + destination + "");

View File

@@ -39,7 +39,7 @@ class InternalSocketRunner implements Runnable {
}
} catch (IOException ex) {
if (this.open) {
_log.error("Error listening for internal connections on " + this.port, ex);
_log.error("Error listening for internal connections on port " + this.port, ex);
}
this.open = false;
}

View File

@@ -16,8 +16,10 @@ import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.data.Base32;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream;
/**
* Coordinate the runtime operation and configuration of a tunnel.
@@ -89,7 +91,7 @@ public class TunnelController implements Logging {
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(keyFile);
fos = new SecureFileOutputStream(keyFile);
Destination dest = client.createDestination(fos);
String destStr = dest.toBase64();
log("Private key created and saved in " + keyFile.getAbsolutePath());
@@ -126,8 +128,8 @@ public class TunnelController implements Logging {
try {
doStartTunnel();
} catch (Exception e) {
_log.error("Error starting up the tunnel", e);
log("Error starting up the tunnel - " + e.getMessage());
_log.error("Error starting the tunnel " + getName(), e);
log("Error starting the tunnel " + getName() + ": " + e.getMessage());
// if we don't acquire() then the release() in stopTunnel() won't work
acquire();
stopTunnel();
@@ -225,6 +227,13 @@ public class TunnelController implements Logging {
setListenOn();
String listenPort = getListenPort();
String sharedClient = getSharedClient();
String proxyList = getProxyList();
if (proxyList != null) {
// set the outproxy property the socks tunnel wants
Properties props = _tunnel.getClientOptions();
if (!props.containsKey(I2PSOCKSTunnel.PROP_PROXY_DEFAULT))
props.setProperty(I2PSOCKSTunnel.PROP_PROXY_DEFAULT, proxyList);
}
_tunnel.runSOCKSTunnel(new String[] { listenPort, sharedClient }, this);
}
@@ -233,6 +242,13 @@ public class TunnelController implements Logging {
setListenOn();
String listenPort = getListenPort();
String sharedClient = getSharedClient();
String proxyList = getProxyList();
if (proxyList != null) {
// set the outproxy property the socks tunnel wants
Properties props = _tunnel.getClientOptions();
if (!props.containsKey(I2PSOCKSTunnel.PROP_PROXY_DEFAULT))
props.setProperty(I2PSOCKSTunnel.PROP_PROXY_DEFAULT, proxyList);
}
if (getPersistentClientKey()) {
String privKeyFile = getPrivKeyFile();
_tunnel.runSOCKSIRCTunnel(new String[] { listenPort, "false", privKeyFile }, this);
@@ -243,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);
@@ -254,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

@@ -20,6 +20,7 @@ import net.i2p.client.I2PSessionException;
import net.i2p.data.DataHelper;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream;
/**
* Coordinate a set of tunnels within the JVM, loading and storing their config
@@ -255,7 +256,7 @@ public class TunnelControllerGroup {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(cfgFile);
fos = new SecureFileOutputStream(cfgFile);
fos.write(buf.toString().getBytes("UTF-8"));
if (_log.shouldLog(Log.INFO))
_log.info("Config written to " + cfgFile.getPath());

View File

@@ -30,13 +30,12 @@ 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 */
public I2PSOCKSIRCTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) {
super(localPort, l, ownDest, notifyThis, tunnel, pkf);
setName(getLocalPort() + " -> SOCKSIRCTunnel");
setName("SOCKS IRC Proxy on " + tunnel.listenHost + ':' + localPort);
}
/**
@@ -47,7 +46,7 @@ public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel {
protected void clientConnectionRun(Socket s) {
try {
//_log.error("SOCKS IRC Tunnel Start");
SOCKSServer serv = SOCKSServerFactory.createSOCKSServer(s);
SOCKSServer serv = SOCKSServerFactory.createSOCKSServer(s, getTunnel().getClientOptions());
Socket clientSock = serv.getClientSocket();
I2PSocket destSock = serv.getDestinationI2PSocket(this);
StringBuffer expectedPong = new StringBuffer();

View File

@@ -15,6 +15,7 @@ import java.util.Properties;
import java.util.StringTokenizer;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelClientBase;
@@ -25,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;
@@ -35,14 +35,14 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
/** @param pkf private key file name or null for transient key */
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) {
super(localPort, ownDest, l, notifyThis, "SOCKSHandler", tunnel, pkf);
super(localPort, ownDest, l, notifyThis, "SOCKS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel, pkf);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openSOCKSTunnelResult", "error");
return;
}
setName(getLocalPort() + " -> SOCKSTunnel");
setName("SOCKS Proxy on " + tunnel.listenHost + ':' + localPort);
parseOptions();
startRunning();
@@ -51,7 +51,7 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
protected void clientConnectionRun(Socket s) {
try {
SOCKSServer serv = SOCKSServerFactory.createSOCKSServer(s);
SOCKSServer serv = SOCKSServerFactory.createSOCKSServer(s, getTunnel().getClientOptions());
Socket clientSock = serv.getClientSocket();
I2PSocket destSock = serv.getDestinationI2PSocket(this);
new I2PTunnelRunner(clientSock, destSock, sockLock, null, mySockets);
@@ -61,15 +61,19 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
}
}
private static final String PROP_PROXY = "i2ptunnel.socks.proxy.";
/** add "default" or port number */
public static final String PROP_PROXY_PREFIX = "i2ptunnel.socks.proxy.";
public static final String DEFAULT = "default";
public static final String PROP_PROXY_DEFAULT = PROP_PROXY_PREFIX + DEFAULT;
private void parseOptions() {
Properties opts = getTunnel().getClientOptions();
proxies = new HashMap(0);
proxies = new HashMap(1);
for (Map.Entry e : opts.entrySet()) {
String prop = (String)e.getKey();
if ((!prop.startsWith(PROP_PROXY)) || prop.length() <= PROP_PROXY.length())
if ((!prop.startsWith(PROP_PROXY_PREFIX)) || prop.length() <= PROP_PROXY_PREFIX.length())
continue;
String port = prop.substring(PROP_PROXY.length());
String port = prop.substring(PROP_PROXY_PREFIX.length());
List proxyList = new ArrayList(1);
StringTokenizer tok = new StringTokenizer((String)e.getValue(), ", \t");
while (tok.hasMoreTokens()) {
@@ -95,7 +99,22 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
}
public List<String> getDefaultProxies() {
return proxies.get("default");
return proxies.get(DEFAULT);
}
/**
* Because getDefaultOptions() in super() is protected
* @since 0.8.2
*/
public I2PSocketOptions buildOptions(Properties overrides) {
Properties defaultOpts = getTunnel().getClientOptions();
defaultOpts.putAll(overrides);
// delayed start
verifySocketManager();
I2PSocketOptions opts = sockMgr.buildOptions(defaultOpts);
if (!defaultOpts.containsKey(I2PSocketOptions.PROP_CONNECT_TIMEOUT))
opts.setConnectTimeout(60 * 1000);
return opts;
}
}

View File

@@ -204,7 +204,7 @@ public class SOCKS4aServer extends SOCKSServer {
// Let's not due a new Dest for every request, huh?
//I2PSocketManager sm = I2PSocketManagerFactory.createManager();
//destSock = sm.connect(I2PTunnel.destFromName(connHostName), null);
destSock = t.createI2PSocket(I2PTunnel.destFromName(connHostName));
destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName));
} else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) {
String err = "No localhost accesses allowed through the Socks Proxy";
_log.error(err);
@@ -237,7 +237,7 @@ public class SOCKS4aServer extends SOCKSServer {
_log.debug("connecting to port " + connPort + " proxy " + proxy + " for " + connHostName + "...");
// this isn't going to work, these need to be socks outproxies so we need
// to do a socks session to them?
destSock = t.createI2PSocket(I2PTunnel.destFromName(proxy));
destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(proxy));
}
confirmConnection();
_log.debug("connection confirmed - exchanging data...");

View File

@@ -16,12 +16,15 @@ import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.util.HexDump;
import net.i2p.util.Log;
@@ -37,8 +40,10 @@ public class SOCKS5Server extends SOCKSServer {
private static final int SOCKS_VERSION_5 = 0x05;
private Socket clientSock = null;
private final Socket clientSock;
private final Properties props;
private boolean setupCompleted = false;
private final boolean authRequired;
/**
* Create a SOCKS5 server that communicates with the client using
@@ -49,9 +54,15 @@ public class SOCKS5Server extends SOCKSServer {
* client socket.
*
* @param clientSock client socket
* @param props non-null
*/
public SOCKS5Server(Socket clientSock) {
public SOCKS5Server(Socket clientSock, Properties props) {
this.clientSock = clientSock;
this.props = props;
this.authRequired =
Boolean.valueOf(props.getProperty(I2PTunnelHTTPClientBase.PROP_AUTH)).booleanValue() &&
props.containsKey(I2PTunnelHTTPClientBase.PROP_USER) &&
props.containsKey(I2PTunnelHTTPClientBase.PROP_PW);
}
public Socket getClientSocket() throws SOCKSException {
@@ -73,7 +84,7 @@ public class SOCKS5Server extends SOCKSServer {
if (manageRequest(in, out) == Command.UDP_ASSOCIATE)
handleUDP(in, out);
} catch (IOException e) {
throw new SOCKSException("Connection error (" + e.getMessage() + ")");
throw new SOCKSException("Connection error: " + e);
}
setupCompleted = true;
@@ -84,31 +95,70 @@ public class SOCKS5Server extends SOCKSServer {
* SOCKS "VER" field has been stripped from the input stream.
*/
private void init(DataInputStream in, DataOutputStream out) throws IOException, SOCKSException {
int nMethods = in.readByte() & 0xff;
int nMethods = in.readUnsignedByte();
boolean methodOk = false;
int method = Method.NO_ACCEPTABLE_METHODS;
for (int i = 0; i < nMethods; ++i) {
int meth = in.readByte() & 0xff;
if (meth == Method.NO_AUTH_REQUIRED) {
int meth = in.readUnsignedByte();
if (((!authRequired) && meth == Method.NO_AUTH_REQUIRED) ||
(authRequired && meth == Method.USERNAME_PASSWORD)) {
// That's fine, we do support this method
method = meth;
}
}
boolean canContinue = false;
switch (method) {
case Method.NO_AUTH_REQUIRED:
case Method.USERNAME_PASSWORD:
_log.debug("username/password authentication required");
sendInitReply(Method.USERNAME_PASSWORD, out);
verifyPassword(in, out);
return;
case Method.NO_AUTH_REQUIRED:
_log.debug("no authentication required");
sendInitReply(Method.NO_AUTH_REQUIRED, out);
return;
default:
default:
_log.debug("no suitable authentication methods found (" + Integer.toHexString(method) + ")");
sendInitReply(Method.NO_ACCEPTABLE_METHODS, out);
throw new SOCKSException("Unsupported authentication method");
}
}
/**
* Wait for the username/password message and verify or throw SOCKSException on failure
* @since 0.8.2
*/
private void verifyPassword(DataInputStream in, DataOutputStream out) throws IOException, SOCKSException {
int c = in.readUnsignedByte();
if (c != AUTH_VERSION)
throw new SOCKSException("Unsupported authentication version");
c = in.readUnsignedByte();
if (c <= 0)
throw new SOCKSException("Bad authentication");
byte[] user = new byte[c];
in.readFully(user);
c = in.readUnsignedByte();
if (c <= 0)
throw new SOCKSException("Bad authentication");
byte[] pw = new byte[c];
in.readFully(pw);
// Hopefully these are in UTF-8, since that's what our config file is in
// these throw UnsupportedEncodingException which is an IOE
String u = new String(user, "UTF-8");
String p = new String(pw, "UTF-8");
String configUser = props.getProperty(I2PTunnelHTTPClientBase.PROP_USER);
String configPW = props.getProperty(I2PTunnelHTTPClientBase.PROP_PW);
if ((!u.equals(configUser)) || (!p.equals(configPW))) {
_log.error("SOCKS authorization failure");
sendAuthReply(AUTH_FAILURE, out);
throw new SOCKSException("SOCKS authorization failure");
}
if (_log.shouldLog(Log.INFO))
_log.info("SOCKS authorization success, user: " + u);
sendAuthReply(AUTH_SUCCESS, out);
}
/**
* SOCKS5 request management. This method assumes that all the
* stuff preceding or enveloping the actual request (e.g. protocol
@@ -116,13 +166,13 @@ public class SOCKS5Server extends SOCKSServer {
* has been stripped out of the input/output streams.
*/
private int manageRequest(DataInputStream in, DataOutputStream out) throws IOException, SOCKSException {
int socksVer = in.readByte() & 0xff;
int socksVer = in.readUnsignedByte();
if (socksVer != SOCKS_VERSION_5) {
_log.debug("error in SOCKS5 request (protocol != 5? wtf?)");
throw new SOCKSException("Invalid protocol version in request: " + socksVer);
}
int command = in.readByte() & 0xff;
int command = in.readUnsignedByte();
switch (command) {
case Command.CONNECT:
break;
@@ -143,17 +193,15 @@ public class SOCKS5Server extends SOCKSServer {
throw new SOCKSException("Invalid command in request");
}
{
// Reserved byte, should be 0x00
byte rsv = in.readByte();
}
// Reserved byte, should be 0x00
in.readByte();
int addressType = in.readByte() & 0xff;
addressType = in.readUnsignedByte();
switch (addressType) {
case AddressType.IPV4:
connHostName = new String("");
for (int i = 0; i < 4; ++i) {
int octet = in.readByte() & 0xff;
int octet = in.readUnsignedByte();
connHostName += Integer.toString(octet);
if (i != 3) {
connHostName += ".";
@@ -164,7 +212,7 @@ public class SOCKS5Server extends SOCKSServer {
break;
case AddressType.DOMAINNAME:
{
int addrLen = in.readByte() & 0xff;
int addrLen = in.readUnsignedByte();
if (addrLen == 0) {
_log.debug("0-sized address length? wtf?");
throw new SOCKSException("Illegal DOMAINNAME length");
@@ -205,7 +253,7 @@ public class SOCKS5Server extends SOCKSServer {
sendRequestReply(Reply.SUCCEEDED, AddressType.IPV4, InetAddress.getByName("127.0.0.1"), null, 1, out);
} catch (IOException e) {
throw new SOCKSException("Connection error (" + e.getMessage() + ")");
throw new SOCKSException("Connection error: " + e);
}
}
@@ -213,17 +261,24 @@ public class SOCKS5Server extends SOCKSServer {
* Send the specified reply during SOCKS5 initialization
*/
private void sendInitReply(int replyCode, DataOutputStream out) throws IOException {
ByteArrayOutputStream reps = new ByteArrayOutputStream();
reps.write(SOCKS_VERSION_5);
reps.write(replyCode);
byte[] reply = reps.toByteArray();
if (_log.shouldLog(Log.DEBUG)) {
byte[] reply = new byte[2];
reply[0] = SOCKS_VERSION_5;
reply[1] = (byte) replyCode;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Sending init reply:\n" + HexDump.dump(reply));
}
out.write(reply);
}
/**
* Send the specified reply during SOCKS5 authorization
* @since 0.8.2
*/
private void sendAuthReply(int replyCode, DataOutputStream out) throws IOException {
byte[] reply = new byte[2];
reply[0] = AUTH_VERSION;
reply[1] = (byte) replyCode;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Sending auth reply:\n" + HexDump.dump(reply));
out.write(reply);
}
@@ -291,7 +346,7 @@ public class SOCKS5Server extends SOCKSServer {
try {
out = new DataOutputStream(clientSock.getOutputStream());
} catch (IOException e) {
throw new SOCKSException("Connection error (" + e.getMessage() + ")");
throw new SOCKSException("Connection error: " + e);
}
// FIXME: here we should read our config file, select an
@@ -305,14 +360,14 @@ public class SOCKS5Server extends SOCKSServer {
// Let's not due a new Dest for every request, huh?
//I2PSocketManager sm = I2PSocketManagerFactory.createManager();
//destSock = sm.connect(I2PTunnel.destFromName(connHostName), null);
Destination dest = I2PTunnel.destFromName(connHostName);
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(connHostName);
if (dest == null) {
try {
sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
} catch (IOException ioe) {}
throw new SOCKSException("Host not found");
}
destSock = t.createI2PSocket(I2PTunnel.destFromName(connHostName));
destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName));
} else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) {
String err = "No localhost accesses allowed through the Socks Proxy";
_log.error(err);
@@ -320,6 +375,7 @@ public class SOCKS5Server extends SOCKSServer {
sendRequestReply(Reply.CONNECTION_NOT_ALLOWED_BY_RULESET, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
} catch (IOException ioe) {}
throw new SOCKSException(err);
/****
} else if (connPort == 80) {
// rewrite GET line to include hostname??? or add Host: line???
// or forward to local eepProxy (but that's a Socket not an I2PSocket)
@@ -330,6 +386,7 @@ public class SOCKS5Server extends SOCKSServer {
sendRequestReply(Reply.CONNECTION_NOT_ALLOWED_BY_RULESET, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
} catch (IOException ioe) {}
throw new SOCKSException(err);
****/
} else {
List<String> proxies = t.getProxies(connPort);
if (proxies == null || proxies.isEmpty()) {
@@ -342,41 +399,182 @@ public class SOCKS5Server extends SOCKSServer {
}
int p = I2PAppContext.getGlobalContext().random().nextInt(proxies.size());
String proxy = proxies.get(p);
_log.debug("connecting to port " + connPort + " proxy " + proxy + " for " + connHostName + "...");
// this isn't going to work, these need to be socks outproxies so we need
// to do a socks session to them?
destSock = t.createI2PSocket(I2PTunnel.destFromName(proxy));
if (_log.shouldLog(Log.DEBUG))
_log.debug("connecting to proxy " + proxy + " for " + connHostName + " port " + connPort);
try {
destSock = outproxyConnect(t, proxy);
} catch (SOCKSException se) {
try {
sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
} catch (IOException ioe) {}
throw se;
}
}
confirmConnection();
_log.debug("connection confirmed - exchanging data...");
} catch (DataFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("socks error", e);
try {
sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
} catch (IOException ioe) {}
throw new SOCKSException("Error in destination format");
} catch (SocketException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("socks error", e);
try {
sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
} catch (IOException ioe) {}
throw new SOCKSException("Error connecting ("
+ e.getMessage() + ")");
throw new SOCKSException("Error connecting: " + e);
} catch (IOException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("socks error", e);
try {
sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
} catch (IOException ioe) {}
throw new SOCKSException("Error connecting ("
+ e.getMessage() + ")");
throw new SOCKSException("Error connecting: " + e);
} catch (I2PException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("socks error", e);
try {
sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
} catch (IOException ioe) {}
throw new SOCKSException("Error connecting ("
+ e.getMessage() + ")");
throw new SOCKSException("Error connecting: " + e);
}
return destSock;
}
/**
* Act as a SOCKS 5 client to connect to an outproxy
* @return open socket or throws error
* @since 0.8.2
*/
private I2PSocket outproxyConnect(I2PSOCKSTunnel tun, String proxy) throws IOException, SOCKSException, DataFormatException, I2PException {
Properties overrides = new Properties();
overrides.setProperty("option.i2p.streaming.connectDelay", "1000");
I2PSocketOptions proxyOpts = tun.buildOptions(overrides);
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(proxy);
if (dest == null)
throw new SOCKSException("Outproxy not found");
I2PSocket destSock = tun.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(proxy), proxyOpts);
try {
DataOutputStream out = new DataOutputStream(destSock.getOutputStream());
boolean authAvail = Boolean.valueOf(props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH)).booleanValue();
String configUser = null;
String configPW = null;
if (authAvail) {
configUser = props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER_PREFIX + proxy);
configPW = props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW_PREFIX + proxy);
if (configUser == null || configPW == null) {
configUser = props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER);
configPW = props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW);
if (configUser == null || configPW == null)
authAvail = false;
}
}
// send the init
out.writeByte(SOCKS_VERSION_5);
if (authAvail) {
out.writeByte(2);
out.writeByte(Method.NO_AUTH_REQUIRED);
out.writeByte(Method.USERNAME_PASSWORD);
} else {
out.writeByte(1);
out.writeByte(Method.NO_AUTH_REQUIRED);
}
out.flush();
// read init reply
DataInputStream in = new DataInputStream(destSock.getInputStream());
// is this right or should we not try to do 5-to-4 conversion?
int hisVersion = in.readByte();
if (hisVersion != SOCKS_VERSION_5 /* && addrtype == AddressType.DOMAINNAME */ )
throw new SOCKSException("SOCKS Outproxy is not Version 5");
//else if (hisVersion != 4)
// throw new SOCKSException("Unsupported SOCKS Outproxy Version");
int method = in.readByte();
if (method == Method.NO_AUTH_REQUIRED) {
// good
} else if (method == Method.USERNAME_PASSWORD) {
if (authAvail) {
// send the auth
out.writeByte(AUTH_VERSION);
byte[] user = configUser.getBytes("UTF-8");
byte[] pw = configPW.getBytes("UTF-8");
out.writeByte(user.length);
out.write(user);
out.writeByte(pw.length);
out.write(pw);
out.flush();
// read the auth reply
if (in.readByte() != AUTH_VERSION)
throw new SOCKSException("Bad auth version from outproxy");
if (in.readByte() != AUTH_SUCCESS)
throw new SOCKSException("Outproxy authorization failure");
} else {
throw new SOCKSException("Outproxy requires authorization, please configure username/password");
}
} else {
throw new SOCKSException("Outproxy authorization failure");
}
// send the connect command
out.writeByte(SOCKS_VERSION_5);
out.writeByte(Command.CONNECT);
out.writeByte(0); // reserved
out.writeByte(addressType);
if (addressType == AddressType.IPV4) {
out.write(InetAddress.getByName(connHostName).getAddress());
} else if (addressType == AddressType.DOMAINNAME) {
byte[] d = connHostName.getBytes("ISO-8859-1");
out.writeByte(d.length);
out.write(d);
} else {
// shouldn't happen
throw new SOCKSException("Unknown address type for outproxy?");
}
out.writeShort(connPort);
out.flush();
// read the connect reply
hisVersion = in.readByte();
if (hisVersion != SOCKS_VERSION_5)
throw new SOCKSException("Outproxy response is not Version 5");
int reply = in.readByte();
in.readByte(); // reserved
int type = in.readByte();
int count = 0;
if (type == AddressType.IPV4) {
count = 4;
} else if (type == AddressType.DOMAINNAME) {
count = in.readUnsignedByte();
} else if (type == AddressType.IPV6) {
count = 16;
} else {
throw new SOCKSException("Unsupported address type in outproxy response");
}
byte[] addr = new byte[count];
in.readFully(addr); // address
in.readUnsignedShort(); // port
if (reply != Reply.SUCCEEDED)
throw new SOCKSException("Outproxy rejected request, response = " + reply);
// throw away the address in the response
// todo pass the response through?
} catch (IOException e) {
try { destSock.close(); } catch (IOException ioe) {}
throw e;
} catch (SOCKSException e) {
try { destSock.close(); } catch (IOException ioe) {}
throw e;
}
// that's it, caller will send confirmation to our client
return destSock;
}
// This isn't really the right place for this, we can't stop the tunnel once it starts.
static SOCKSUDPTunnel _tunnel;
static final Object _startLock = new Object();
@@ -435,6 +633,7 @@ public class SOCKS5Server extends SOCKSServer {
*/
private static class Method {
private static final int NO_AUTH_REQUIRED = 0x00;
private static final int USERNAME_PASSWORD = 0x02;
private static final int NO_ACCEPTABLE_METHODS = 0xff;
}
@@ -461,4 +660,8 @@ public class SOCKS5Server extends SOCKSServer {
private static final int COMMAND_NOT_SUPPORTED = 0x07;
private static final int ADDRESS_TYPE_NOT_SUPPORTED = 0x08;
}
private static final int AUTH_VERSION = 1;
private static final int AUTH_SUCCESS = 0;
private static final int AUTH_FAILURE = 1;
}

View File

@@ -1,7 +1,7 @@
package net.i2p.i2ptunnel.socks;
import net.i2p.I2PAppContext;
import net.i2p.data.Base32;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
@@ -74,11 +74,8 @@ public class SOCKSHeader {
String name = getHost();
if (name == null)
return null;
try {
// the naming service does caching (thankfully)
return I2PTunnel.destFromName(name);
} catch (DataFormatException dfe) {}
return null;
// the naming service does caching (thankfully)
return I2PAppContext.getGlobalContext().namingService().lookup(name);
}
public byte[] getBytes() {

View File

@@ -20,8 +20,9 @@ public abstract class SOCKSServer {
private static final Log _log = new Log(SOCKSServer.class);
/* Details about the connection requested by client */
protected String connHostName = null;
protected int connPort = 0;
protected String connHostName;
protected int connPort;
protected int addressType;
/**
* Perform server initialization (expecially regarding protected

View File

@@ -10,7 +10,9 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Properties;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.util.Log;
/**
@@ -35,8 +37,9 @@ public class SOCKSServerFactory {
* provided sockets's input stream.
*
* @param s a Socket used to choose the SOCKS server type
* @param props non-null
*/
public static SOCKSServer createSOCKSServer(Socket s) throws SOCKSException {
public static SOCKSServer createSOCKSServer(Socket s, Properties props) throws SOCKSException {
SOCKSServer serv;
try {
@@ -46,11 +49,16 @@ public class SOCKSServerFactory {
switch (socksVer) {
case 0x04:
// SOCKS version 4/4a
if (Boolean.valueOf(props.getProperty(I2PTunnelHTTPClientBase.PROP_AUTH)).booleanValue() &&
props.containsKey(I2PTunnelHTTPClientBase.PROP_USER) &&
props.containsKey(I2PTunnelHTTPClientBase.PROP_PW)) {
throw new SOCKSException("SOCKS 4/4a not supported when authorization is required");
}
serv = new SOCKS4aServer(s);
break;
case 0x05:
// SOCKS version 5
serv = new SOCKS5Server(s);
serv = new SOCKS5Server(s, props);
break;
case 'C':
case 'G':

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;
@@ -117,9 +116,7 @@ import net.i2p.util.Log;
// Setup the sink. Always send repliable datagrams.
if (destination != null && destination.length() > 0) {
try {
_otherDest = I2PTunnel.destFromName(destination);
} catch (DataFormatException dfe) {}
_otherDest = _context.namingService().lookup(destination);
if (_otherDest == null) {
l.log("Could not resolve " + destination);
throw new RuntimeException("failed to create session - could not resolve " + destination);

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,9 +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
@@ -68,6 +77,31 @@ public class EditBean extends IndexBean {
return "i2ptunnel" + tunnel + "-privKeys.dat";
}
public String getNameSignature(int tunnel) {
String spoof = getSpoofedHost(tunnel);
if (spoof.length() <= 0)
return "";
TunnelController tun = getController(tunnel);
if (tun == null)
return "";
String keyFile = tun.getPrivKeyFile();
if (keyFile != null && keyFile.trim().length() > 0) {
PrivateKeyFile pkf = new PrivateKeyFile(keyFile);
try {
Destination d = pkf.getDestination();
if (d == null)
return "";
SigningPrivateKey privKey = pkf.getSigningPrivKey();
if (privKey == null)
return "";
//System.err.println("Signing " + spoof + " with " + Base64.encode(privKey.getData()));
Signature sig = _context.dsa().sign(spoof.getBytes("UTF-8"), privKey);
return Base64.encode(sig.getData());
} catch (Exception e) {}
}
return "";
}
public boolean startAutomatically(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
@@ -140,12 +174,21 @@ 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", "").replaceAll(",", "\n");
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) {
@@ -170,6 +213,68 @@ public class EditBean extends IndexBean {
return getBooleanProperty(tunnel, "i2cp.delayOpen");
}
/** all proxy auth @since 0.8.2 */
public boolean getProxyAuth(int tunnel) {
return getBooleanProperty(tunnel, I2PTunnelHTTPClientBase.PROP_AUTH) &&
getProxyUsername(tunnel).length() > 0 &&
getProxyPassword(tunnel).length() > 0;
}
public String getProxyUsername(int tunnel) {
return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_USER, "");
}
public String getProxyPassword(int tunnel) {
if (getProxyUsername(tunnel).length() <= 0)
return "";
return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_PW, "");
}
public boolean getOutproxyAuth(int tunnel) {
return getBooleanProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH) &&
getOutproxyUsername(tunnel).length() > 0 &&
getOutproxyPassword(tunnel).length() > 0;
}
public String getOutproxyUsername(int tunnel) {
return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER, "");
}
public String getOutproxyPassword(int tunnel) {
if (getOutproxyUsername(tunnel).length() <= 0)
return "";
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) {
@@ -206,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();
@@ -215,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

@@ -9,6 +9,7 @@ package net.i2p.i2ptunnel.web;
*/
import java.util.concurrent.ConcurrentHashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -23,6 +24,8 @@ 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;
import net.i2p.util.ConcurrentHashSet;
@@ -41,10 +44,10 @@ public class IndexBean {
protected TunnelControllerGroup _group;
private String _action;
private int _tunnel;
private long _prevNonce;
private long _prevNonce2;
private long _curNonce;
private long _nextNonce;
//private long _prevNonce;
//private long _prevNonce2;
private String _curNonce;
//private long _nextNonce;
private String _type;
private String _name;
@@ -60,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;
@@ -85,10 +87,14 @@ public class IndexBean {
/** deprecated unimplemented, now using routerconsole realm */
//public static final String PROP_TUNNEL_PASSPHRASE = "i2ptunnel.passphrase";
public static final String PROP_TUNNEL_PASSPHRASE = "consolePassword";
static final String PROP_NONCE = IndexBean.class.getName() + ".nonce";
static final String PROP_NONCE_OLD = PROP_NONCE + '2';
//static final String PROP_NONCE = IndexBean.class.getName() + ".nonce";
//static final String PROP_NONCE_OLD = PROP_NONCE + '2';
/** 3 wasn't enough for some browsers. They are reloading the page for some reason - maybe HEAD? @since 0.8.1 */
private static final int MAX_NONCES = 8;
/** store nonces in a static FIFO instead of in System Properties @since 0.8.1 */
private static final List<String> _nonces = new ArrayList(MAX_NONCES + 1);
static final String CLIENT_NICKNAME = "shared clients";
public static final String PROP_THEME_NAME = "routerconsole.theme";
public static final String DEFAULT_THEME = "light";
public static final String PROP_CSS_DISABLED = "routerconsole.css.disabled";
@@ -98,34 +104,39 @@ public class IndexBean {
_context = I2PAppContext.getGlobalContext();
_log = _context.logManager().getLog(IndexBean.class);
_group = TunnelControllerGroup.getInstance();
_action = null;
_tunnel = -1;
_curNonce = -1;
_prevNonce = -1;
_prevNonce2 = -1;
try {
String nonce2 = System.getProperty(PROP_NONCE_OLD);
if (nonce2 != null)
_prevNonce2 = Long.parseLong(nonce2);
String nonce = System.getProperty(PROP_NONCE);
if (nonce != null) {
_prevNonce = Long.parseLong(nonce);
System.setProperty(PROP_NONCE_OLD, nonce);
}
} catch (NumberFormatException nfe) {}
_nextNonce = _context.random().nextLong();
System.setProperty(PROP_NONCE, Long.toString(_nextNonce));
_curNonce = "-1";
addNonce();
_booleanOptions = new ConcurrentHashSet(4);
_otherOptions = new ConcurrentHashMap(4);
}
public long getNextNonce() { return _nextNonce; }
public static String getNextNonce() {
synchronized (_nonces) {
return _nonces.get(0);
}
}
public void setNonce(String nonce) {
if ( (nonce == null) || (nonce.trim().length() <= 0) ) return;
try {
_curNonce = Long.parseLong(nonce);
} catch (NumberFormatException nfe) {
_curNonce = -1;
_curNonce = nonce;
}
/** add a random nonce to the head of the queue @since 0.8.1 */
private void addNonce() {
String nextNonce = Long.toString(_context.random().nextLong());
synchronized (_nonces) {
_nonces.add(0, nextNonce);
int sz = _nonces.size();
if (sz > MAX_NONCES)
_nonces.remove(sz - 1);
}
}
/** do we know this nonce? @since 0.8.1 */
private static boolean haveNonce(String nonce) {
synchronized (_nonces) {
return _nonces.contains(nonce);
}
}
@@ -155,8 +166,8 @@ public class IndexBean {
private String processAction() {
if ( (_action == null) || (_action.trim().length() <= 0) || ("Cancel".equals(_action)))
return "";
if ( (_prevNonce != _curNonce) && (_prevNonce2 != _curNonce) && (!validPassphrase()) )
return "Invalid form submission, probably because you used the 'back' or 'reload' button on your browser. Please resubmit.";
if ( (!haveNonce(_curNonce)) && (!validPassphrase()) )
return _("Invalid form submission, probably because you used the 'back' or 'reload' button on your browser. Please resubmit.");
if ("Stop all".equals(_action))
return stopAll();
else if ("Start all".equals(_action))
@@ -203,7 +214,7 @@ public class IndexBean {
if (_group == null) return "";
_group.reloadControllers();
return "Config reloaded";
return _("Configuration reloaded for all tunnels");
}
private String start() {
if (_tunnel < 0) return "Invalid tunnel";
@@ -212,7 +223,10 @@ public class IndexBean {
if (_tunnel >= controllers.size()) return "Invalid tunnel";
TunnelController controller = (TunnelController)controllers.get(_tunnel);
controller.startTunnelBackground();
return "";
// give the messages a chance to make it to the window
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
// and give them something to look at in any case
return _("Starting tunnel") + ' ' + getTunnelName(_tunnel) + "&hellip;";
}
private String stop() {
@@ -222,7 +236,10 @@ public class IndexBean {
if (_tunnel >= controllers.size()) return "Invalid tunnel";
TunnelController controller = (TunnelController)controllers.get(_tunnel);
controller.stopTunnel();
return "";
// give the messages a chance to make it to the window
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
// and give them something to look at in any case
return _("Stopping tunnel") + ' ' + getTunnelName(_tunnel) + "&hellip;";
}
private String saveChanges() {
@@ -414,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) {
@@ -460,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 "";
}
@@ -520,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);
}
@@ -557,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);
@@ -626,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");
}
@@ -654,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().replaceAll("\r\n", ",").replaceAll("\n", ",").replaceAll(" ", ","));
_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 {
@@ -666,6 +720,79 @@ public class IndexBean {
}
}
/** all proxy auth @since 0.8.2 */
public void setProxyAuth(String s) {
_booleanOptions.add(I2PTunnelHTTPClientBase.PROP_AUTH);
}
public void setProxyUsername(String s) {
if (s != null)
_otherOptions.put(I2PTunnelHTTPClientBase.PROP_USER, s.trim());
}
public void setProxyPassword(String s) {
if (s != null)
_otherOptions.put(I2PTunnelHTTPClientBase.PROP_PW, s.trim());
}
public void setOutproxyAuth(String s) {
_booleanOptions.add(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH);
}
public void setOutproxyUsername(String s) {
if (s != null)
_otherOptions.put(I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER, s.trim());
}
public void setOutproxyPassword(String s) {
if (s != null)
_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) {
@@ -785,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));
@@ -804,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)
@@ -815,10 +945,16 @@ public class IndexBean {
config.setProperty("option." + p, _otherOptions.get(p));
}
if ("httpclient".equals(_type) || "connectclient".equals(_type)) {
// generic proxy stuff
if ("httpclient".equals(_type) || "connectclient".equals(_type) ||
"sockstunnel".equals(_type) ||"socksirctunnel".equals(_type)) {
for (String p : _booleanProxyOpts)
config.setProperty("option." + p, "" + _booleanOptions.contains(p));
if (_proxyList != null)
config.setProperty("proxyList", _proxyList);
} else if ("ircclient".equals(_type) || "client".equals(_type) || "streamrclient".equals(_type)) {
}
if ("ircclient".equals(_type) || "client".equals(_type) || "streamrclient".equals(_type)) {
if (_targetDestination != null)
config.setProperty("targetDestination", _targetDestination);
} else if ("httpserver".equals(_type) || "httpbidirserver".equals(_type)) {
@@ -828,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);
@@ -848,19 +982,28 @@ public class IndexBean {
private static final String _booleanClientOpts[] = {
"i2cp.reduceOnIdle", "i2cp.closeOnIdle", "i2cp.newDestOnResume", "persistentClientKey", "i2cp.delayOpen"
};
private static final String _booleanProxyOpts[] = {
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"
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime",
"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));
_noShowSet.addAll(Arrays.asList(_booleanProxyOpts));
_noShowSet.addAll(Arrays.asList(_booleanServerOpts));
_noShowSet.addAll(Arrays.asList(_otherClientOpts));
_noShowSet.addAll(Arrays.asList(_otherServerOpts));
@@ -872,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);
@@ -950,19 +1095,20 @@ public class IndexBean {
return null;
}
private String getMessages(List msgs) {
private static String getMessages(List msgs) {
StringBuilder buf = new StringBuilder(128);
getMessages(msgs, buf);
return buf.toString();
}
private void getMessages(List msgs, StringBuilder buf) {
private static void getMessages(List msgs, StringBuilder buf) {
if (msgs == null) return;
for (int i = 0; i < msgs.size(); i++) {
buf.append((String)msgs.get(i)).append("\n");
}
}
private String _(String key) {
protected String _(String key) {
return Messages._(key, _context);
}
}

View File

@@ -29,7 +29,7 @@
<div id="pageHeader">
</div>
<form method="post" action="index.jsp">
<form method="post" action="list">
<div id="tunnelEditPanel" class="panel">
<div class="header">
@@ -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,51 +95,46 @@
</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>
<% if ("httpclient".equals(tunnelType) || "connectclient".equals(tunnelType)) {
<% if ("httpclient".equals(tunnelType) || "connectclient".equals(tunnelType) || "sockstunnel".equals(tunnelType) || "socksirctunnel".equals(tunnelType)) {
%><div id="destinationField" class="rowItem">
<label for="proxyList" accesskey="x">
<%=intl._("Outproxies")%>(<span class="accessKey">x</span>):
@@ -159,7 +154,7 @@
%>
</label>
<input type="text" size="30" id="targetDestination" name="targetDestination" title="Destination of the Tunnel" value="<%=editBean.getClientDestination(curTunnel)%>" class="freetext" />
<span class="comment">(<%=intl._("name or destination")%>)</span>
<span class="comment">(<%=intl._("name or destination")%>; <%=intl._("b32 not recommended")%>)</span>
</div>
<% } %>
<% if (!"streamrclient".equals(tunnelType)) { %>
@@ -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="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>
<% if (!"streamrclient".equals(tunnelType)) { // streamr client sends pings so it will never be idle %>
@@ -414,6 +409,69 @@
</div>
<% } %>
<% if ("httpclient".equals(tunnelType) || "connectclient".equals(tunnelType) || "sockstunnel".equals(tunnelType) || "socksirctunnel".equals(tunnelType)) { %>
<div id="accessField" class="rowItem">
<label><%=intl._("Local Authorization")%>:</label>
</div>
<div id="portField" class="rowItem">
<label>
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="proxyAuth" name="proxyAuth" title="Check to require authorization for this service"<%=(editBean.getProxyAuth(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="portField" class="rowItem">
<label>
<%=intl._("Username")%>:
</label>
<input type="text" id="clientPort" name="proxyUsername" title="Set username for this service" value="<%=editBean.getProxyUsername(curTunnel)%>" class="freetext" />
</div>
<div id="portField" class="rowItem">
<label>
<%=intl._("Password")%>:
</label>
<input type="password" id="clientPort" name="proxyPassword" title="Set password for this service" value="<%=editBean.getProxyPassword(curTunnel)%>" class="freetext" />
</div>
<div class="subdivider">
<hr />
</div>
<div id="accessField" class="rowItem">
<label><%=intl._("Outproxy Authorization")%>:</label>
</div>
<div id="portField" class="rowItem">
<label>
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="outproxyAuth" name="outproxyAuth" title="Check if the outproxy requires authorization"<%=(editBean.getOutproxyAuth(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="portField" class="rowItem">
<label>
<%=intl._("Username")%>:
</label>
<input type="text" id="clientPort" name="outproxyUsername" title="Enter username required by outproxy" value="<%=editBean.getOutproxyUsername(curTunnel)%>" class="freetext" />
</div>
<div id="portField" class="rowItem">
<label>
<%=intl._("Password")%>:
</label>
<input type="password" id="clientPort" name="outproxyPassword" title="Enter password required by outproxy" value="<%=editBean.getOutproxyPassword(curTunnel)%>" class="freetext" />
</div>
<div class="subdivider">
<hr />
</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

@@ -29,7 +29,7 @@
<div id="pageHeader">
</div>
<form method="post" action="index.jsp">
<form method="post" action="list">
<div id="tunnelEditPanel" class="panel">
<div class="header">
@@ -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>
@@ -196,7 +191,16 @@
<a href="/susidns/addressbook.jsp?book=private&hostname=<%=editBean.getTunnelName(curTunnel)%>&destination=<%=editBean.getDestinationBase64(curTunnel)%>#add"><%=intl._("Add to local addressbook")%></a>
<% } %>
</div>
<% if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
%><div id="sigField" class="rowItem">
<label for="signature">
<%=intl._("Hostname Signature")%>
</label>
<input type="text" size="30" readonly="readonly" title="Use to prove that the website name is for this destination" value="<%=editBean.getNameSignature(curTunnel)%>" wrap="off" class="freetext" />
</div>
<% } %>
<div class="footer">
</div>
</div>
@@ -293,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">
@@ -324,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">
@@ -350,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

@@ -1,2 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>I2P Router Console</title></head>
<body><meta http-equiv="refresh" content="0;url=index.jsp" /><a href="index.jsp">Enter</a></body></html>

View File

@@ -44,7 +44,7 @@
<div class="footer">
<div class="toolbox">
<a class="control" href="index.jsp"><%=intl._("Refresh")%></a>
<a class="control" href="list"><%=intl._("Refresh")%></a>
</div>
</div>
</div>
@@ -53,7 +53,7 @@
<div class="header"></div>
<div class="footer">
<div class="toolbox">
<a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=Stop%20all"><%=intl._("Stop All")%></a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=Start%20all"><%=intl._("Start All")%></a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=Restart%20all"><%=intl._("Restart All")%></a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=Reload%20configuration"><%=intl._("Reload Config")%></a>
<a class="control" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=Stop%20all"><%=intl._("Stop All")%></a> <a class="control" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=Start%20all"><%=intl._("Start All")%></a> <a class="control" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=Restart%20all"><%=intl._("Restart All")%></a> <a class="control" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=Reload%20configuration"><%=intl._("Reload Config")%></a>
</div>
</div>
</div>
@@ -89,13 +89,13 @@
%>
<div class="nameField rowItem">
<label><%=intl._("Name")%>:</label>
<span class="text"><a href="edit.jsp?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>"><%=indexBean.getTunnelName(curServer)%></a></span>
<span class="text"><a href="edit?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>"><%=indexBean.getTunnelName(curServer)%></a></span>
</div>
<div class="previewField rowItem">
<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>
<%
@@ -125,17 +125,17 @@
switch (indexBean.getTunnelStatus(curServer)) {
case IndexBean.STARTING:
%><div class="statusStarting text"><%=intl._("Starting...")%></div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curServer%>"><%=intl._("Stop")%></a>
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curServer%>"><%=intl._("Stop")%></a>
<%
break;
case IndexBean.RUNNING:
%><div class="statusRunning text"><%=intl._("Running")%></div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curServer%>"><%=intl._("Stop")%></a>
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curServer%>"><%=intl._("Stop")%></a>
<%
break;
case IndexBean.NOT_RUNNING:
%><div class="statusNotRunning text"><%=intl._("Stopped")%></div>
<a class="control" title="Start this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=start&amp;tunnel=<%=curServer%>"><%=intl._("Start")%></a>
<a class="control" title="Start this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=start&amp;tunnel=<%=curServer%>"><%=intl._("Start")%></a>
<%
break;
}
@@ -157,7 +157,7 @@
</div>
<div class="footer">
<form id="addNewServerTunnelForm" action="edit.jsp">
<form id="addNewServerTunnelForm" action="edit">
<div class="toolbox">
<label><%=intl._("New server tunnel")%>:</label>
@@ -209,11 +209,22 @@
%>
<div class="nameField rowItem">
<label><%=intl._("Name")%>:</label>
<span class="text"><a href="edit.jsp?tunnel=<%=curClient%>" title="Edit Tunnel Settings for <%=indexBean.getTunnelName(curClient)%>"><%=indexBean.getTunnelName(curClient)%></a></span>
<span class="text"><a href="edit?tunnel=<%=curClient%>" title="Edit Tunnel Settings for <%=indexBean.getTunnelName(curClient)%>"><%=indexBean.getTunnelName(curClient)%></a></span>
</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>
@@ -229,40 +252,45 @@
switch (indexBean.getTunnelStatus(curClient)) {
case IndexBean.STARTING:
%><div class="statusStarting text"><%=intl._("Starting...")%></div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
<%
break;
case IndexBean.STANDBY:
%><div class="statusStarting text"><%=intl._("Standby")%></div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
<%
break;
case IndexBean.RUNNING:
%><div class="statusRunning text"><%=intl._("Running")%></div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
<a class="control" title="Stop this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>"><%=intl._("Stop")%></a>
<%
break;
case IndexBean.NOT_RUNNING:
%><div class="statusNotRunning text"><%=intl._("Stopped")%></div>
<a class="control" title="Start this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=start&amp;tunnel=<%=curClient%>"><%=intl._("Start")%></a>
<a class="control" title="Start this Tunnel" href="list?nonce=<%=indexBean.getNextNonce()%>&amp;action=start&amp;tunnel=<%=curClient%>"><%=intl._("Start")%></a>
<%
break;
}
%></div>
<% if (!("sockstunnel".equals(indexBean.getInternalType(curClient)) ||
"socksirctunnel".equals(indexBean.getInternalType(curClient)))) { %>
<div class="destinationField rowItem">
<label>
<% if ("httpclient".equals(indexBean.getInternalType(curClient)) || "connectclient".equals(indexBean.getInternalType(curClient))) { %>
<% if ("httpclient".equals(indexBean.getInternalType(curClient)) || "connectclient".equals(indexBean.getInternalType(curClient)) ||
"sockstunnel".equals(indexBean.getInternalType(curClient)) || "socksirctunnel".equals(indexBean.getInternalType(curClient))) { %>
<%=intl._("Outproxy")%>:
<% } else { %>
<%=intl._("Destination")%>:
<% } %>
</label>
<input class="freetext" size="40" readonly="readonly" value="<%=indexBean.getClientDestination(curClient)%>" />
<div class="text">
<% String cdest = indexBean.getClientDestination(curClient);
if (cdest.length() > 0) {
%><%=cdest%><%
} else {
%><i><%=intl._("none")%></i><%
} %>
</div>
</div>
<% } %>
<div class="descriptionField rowItem">
<label><%=intl._("Description")%>:</label>
@@ -280,7 +308,7 @@
</div>
<div class="footer">
<form id="addNewClientTunnelForm" action="edit.jsp">
<form id="addNewClientTunnelForm" action="edit">
<div class="toolbox">
<label><%=intl._("New client tunnel")%>:</label>

View File

@@ -5,6 +5,19 @@
<web-app>
<!-- precompiled servlets -->
<!-- yeah we could do this in a handler but this is easier -->
<servlet-mapping>
<servlet-name>net.i2p.i2ptunnel.jsp.index_jsp</servlet-name>
<!-- this becomes the default so it also covers /index and /index.html -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>net.i2p.i2ptunnel.jsp.edit_jsp</servlet-name>
<url-pattern>/edit</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30

View File

@@ -8,87 +8,105 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-06-13 19:23+0000\n"
"PO-Revision-Date: 2010-06-15 14:09+0100\n"
"Last-Translator: echelon <echelon@i2pmail.org>\n"
"POT-Creation-Date: 2010-12-04 17:23+0000\n"
"PO-Revision-Date: 2010-12-19 04:36+0100\n"
"Last-Translator: mixxy <m1xxy@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: German\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:493
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:475
#, 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 "Um das Ziel in ihrer Host Datenbank zu besuchen, klicken Sie <a href=\"{0}\">hier</a>. Um das Ziel aus der kollidierenden Adresshelfer Anfrage zu besuchen, klicken Sie <a href=\"{1}\">hier</a>."
msgstr "Um das Ziel in Ihrer Host-Datenbank zu besuchen, klicken Sie <a href=\"{0}\">hier</a>, und um das Ziel aus der kollidierenden Adresshelfer-Anfrage zu besuchen, <a href=\"{1}\">hier</a>!"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:909
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:932
msgid "Click a link below to look for an address helper by using a \"jump\" service:"
msgstr "Durch klicken auf einen der unten stehenden Links bekommen Sie einen Adresshelfer von einem \"Jump\" Service:"
msgstr "Durch Klicken auf einen der untenstehenden Links bekommen Sie einen Adresshelfer von einem \"Sprung\"-Service:"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:369
#: ../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 "Ungültige Formulareingabe - wahrscheinlich haben Sie den \"Zurück\"-Knopf Ihres Browsers betätigt. Bitte neuladen!"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:217
msgid "Configuration reloaded for all tunnels"
msgstr "Einstellungen für alle Tunnel neugeladen"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:229
msgid "Starting tunnel"
msgstr "Starte Tunnel ..."
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:242
msgid "Stopping tunnel"
msgstr "Beende Tunnel ..."
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:389
msgid "New Tunnel"
msgstr "Neuer Tunnel"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:389
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:409
msgid "Standard client"
msgstr "Standard Klient"
msgstr "Standardklient"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:390
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:410
msgid "HTTP client"
msgstr "HTTP Klient"
msgstr "HTTP-Klient"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:391
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:411
msgid "IRC client"
msgstr "IRC Klient"
msgstr "IRC-Klient"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:392
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:412
msgid "Standard server"
msgstr "Standard Server"
msgstr "Standardserver"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:393
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:413
msgid "HTTP server"
msgstr "HTTP Server"
msgstr "HTTP-Server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:394
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:414
msgid "SOCKS 4/4a/5 proxy"
msgstr "SOCKS 4/4a/5 Proxy"
msgstr "SOCKS-4/4a/5-Proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:395
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:415
msgid "SOCKS IRC proxy"
msgstr "SOCKS IRC Proxy"
msgstr "SOCKS-IRC-Proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:396
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:416
msgid "CONNECT/SSL/HTTPS proxy"
msgstr "CONNECT/SSL/HTTPS Proxy"
msgstr "CONNECT/SSL/HTTPS-Proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:397
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:417
msgid "IRC server"
msgstr "IRC Server"
msgstr "IRC-Server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:398
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:418
msgid "Streamr client"
msgstr "Streamr Klient"
msgstr "Streamr-Klient"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:399
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:419
msgid "Streamr server"
msgstr "Streamr Server"
msgstr "Streamr-Server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:400
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:420
msgid "HTTP bidir"
msgstr "HTTP Bidir"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:73
msgid "I2P Tunnel Manager - Edit Client Tunnel"
msgstr "I2P Tunnel Manager - Edit Klienten Tunnel"
msgstr "I2P-Tunnel-Manager - Kliententunnel bearbeiten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:93
msgid "Edit proxy settings"
msgstr "Editiere Proxy Einstellungen"
msgstr "Proxyeinstellungen bearbeiten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:101
msgid "New proxy settings"
msgstr "Neue Proxy Einstellungen"
msgstr "Neue Proxyeinstellungen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:112
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:112
@@ -109,7 +127,7 @@ msgstr "Typ"
#: ../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:358
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:367
msgid "Description"
msgstr "Beschreibung"
@@ -147,17 +165,17 @@ msgstr "Lokal (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 "Jeder (0.0.0.0)"
msgstr "Überall (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 (Bitte geben Sie ihre LAN Adressen an)"
msgstr "LAN-Hosts (Bitte geben Sie ihre LAN-Adressen an!)"
#: ../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 "Andere"
msgstr "Anderen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:195
msgid "Outproxies"
@@ -165,302 +183,326 @@ msgstr "Ausgehende Proxies"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:202
msgid "Tunnel Destination"
msgstr "Tunnel Ziel"
msgstr "Ziel des Tunnels"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:214
msgid "name or destination"
msgstr "Name oder Ziel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:220
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:237
msgid "Profile"
msgstr "Profil"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:217
msgid "b32 not recommended"
msgstr "B32-Adressen nicht empfohlen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:223
msgid "Shared Client"
msgstr "versch. Klienten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:244
msgid "interactive connection"
msgstr "Interaktive Verbindung"
msgid "(Share tunnels with other clients and irc/httpclients? Change requires restart of client proxy)"
msgstr "(Soll dieser Tunnel mit anderen Klienten und IRC/HTTP-Klienten geteilt werden? Änderungen benötigen Neustart des Klientenproxys)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:231
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:248
msgid "bulk connection (downloads/websites/BT)"
msgstr "lose Verbindung (Download/Webseiten/BitTorrent)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:233
msgid "Delay Connect"
msgstr "Verbindung verzögern"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:237
msgid "for request/response connections"
msgstr "für Verbindungen mit Anfragen/Antworten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239
msgid "Shared Client"
msgstr "Geteilter Klient"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:243
msgid "(Share tunnels with other clients and irc/httpclients? Change requires restart of client proxy)"
msgstr "(Teile Tunnel mit anderen Klienten und IRC/HTTP Klienten? Änderungen benötigen Neustart des Klientenproxys)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:247
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:124
msgid "Auto Start"
msgstr "Automatischer Start"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:251
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:235
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:128
msgid "(Check the Box for 'YES')"
msgstr "(Aktiviere die Box für 'JA')"
msgstr "(Aktiviere das Kästchen für 'ja')"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:253
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:266
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:237
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:258
msgid "Advanced networking options"
msgstr "Erweiterte Netzwerk Optionen"
msgstr "Erweiterte Netzwerkoptionen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:255
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239
msgid "(NOTE: when this client proxy is configured to share tunnels, then these options are for all the shared proxy clients!)"
msgstr "(HINWEIS: Ist dieser Klienten Proxy auf Teilen der Tunnel konfiguriert, dann gelten diese Optionen für alle Klienten des Proxy Klienten!)"
msgstr "(HINWEIS: Ist dieser Proxy konfiguriert, Tunnel mit anderen Klienten zu teilen, so gelten diese Optionen für alle Klienten des Proxys!)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:257
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:268
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:241
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:260
msgid "Tunnel Options"
msgstr "Tunnel Optionen"
msgstr "Tunneloptionen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:259
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:270
#: ../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 "Length"
msgstr "Länge"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:266
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:277
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:250
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:269
msgid "0 hop tunnel (low anonymity, low latency)"
msgstr "0 Hop Tunnel (geringe Anonymität, geringe Latenz)"
msgstr "0-Hop-Tunnel (geringe Anonymität, geringe Latenz)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:270
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:254
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:273
msgid "1 hop tunnel (medium anonymity, medium latency)"
msgstr "1 Hop Tunnel (mittlere Anonymität, mittlere Latenz)"
msgstr "1-Hop-Tunnel (mittlere Anonymität, mittlere Latenz)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:274
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:285
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:258
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:277
msgid "2 hop tunnel (high anonymity, high latency)"
msgstr "2 Hop Tunnel (hohe Anonymität, hohe Latenz)"
msgstr "2-Hop-Tunnel (hohe Anonymität, hohe Latenz)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:278
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:289
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:262
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281
msgid "3 hop tunnel (very high anonymity, poor performance)"
msgstr "3 Hop Tunnel (sehr hohe Anonymität, geringe Performance)"
msgstr "3-Hop-Tunnel (sehr hohe Anonymität, geringe Leistung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:287
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:298
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:271
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:290
msgid "hop tunnel (very poor performance)"
msgstr "Hop Tunnel (sehr geringe Performance)"
msgstr "Hop-Tunnel (sehr geringe Leistung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:292
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:303
#: ../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 "Variance"
msgstr "Varianz"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:299
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:310
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:283
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:302
msgid "0 hop variance (no randomisation, consistant performance)"
msgstr "0 Hop Varianz (keine zufällige Verteilung, konsistente Performance)"
msgstr "0-Hop-Varianz (keine zufällige Längenveränderung, konsistente Leistung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:303
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:314
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:287
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:306
msgid "+ 0-1 hop variance (medium additive randomisation, subtractive performance)"
msgstr "+ 0-1 Hop Varianz (mittlere, hinzufügende zufällige Verteilung, verringert Performance)"
msgstr "+ 0-1 Hop Varianz (mittlere zufällige Verlängerung, verringert die Leistung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:307
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:318
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:291
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:310
msgid "+ 0-2 hop variance (high additive randomisation, subtractive performance)"
msgstr "+ 0-2 Hop Varianz (hohe, hinzufügende zufällige Verteilung, verringert Performance)"
msgstr "+ 0-2 Hops Varianz (hohe zufällige Verlängerung, verringerte Leistung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:295
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:314
msgid "+/- 0-1 hop variance (standard randomisation, standard performance)"
msgstr "+/- 0-1 Hop Varianz (geringe zufällige Längenänderung, Standardleistung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:299
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:318
msgid "+/- 0-2 hop variance (not recommended)"
msgstr "+/- 0-2 Hops Varianz (nicht empfohlen)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:311
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:322
msgid "+/- 0-1 hop variance (standard randomisation, standard performance)"
msgstr "+ 0-1 Hop Varianz (standard zufällige Verteilung, standard Performance)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:330
msgid "hop variance"
msgstr "Hops Varianz"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:315
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:326
msgid "+/- 0-2 hop variance (not recommended)"
msgstr "+/- 0-2 Hop Varianz (nicht empfohlen)"
#: ../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 "Count"
msgstr "Anzahl"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:323
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:342
msgid "1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)"
msgstr "1 eingehender, 1 ausgehender Tunnel (geringe Bandbreitennutzung, weniger zuverlässig)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:327
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:338
msgid "hop variance"
msgstr "Hop Varianz"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:332
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:343
msgid "Count"
msgstr "Zähler"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:339
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:350
msgid "1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)"
msgstr "1 eingehender, 1 ausgehender Tunnel (geringe Bandbreitennutzung, wenig Zuverlässigkeit)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:343
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:354
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:346
msgid "2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)"
msgstr "2 eingehende, 2 ausgehende Tunnel (standard Bandbreitennutzung, standard Zuverlässigkeit)"
msgstr "2 eingehende, 2 ausgehende Tunnel (Standardbandbreitennutzung, zuverlässig)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:347
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:358
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:331
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:350
msgid "3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)"
msgstr "3 eingehende, 3 ausgehende Tunnel (hohe Bandbreitennutzung, hohe Zuverlässigkeit)"
msgstr "3 eingehende, 3 ausgehende Tunnel (hohe Bandbreitennutzung, zuverlässiger)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:356
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:367
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:340
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:359
msgid "tunnels"
msgstr "Tunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:361
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:372
#: ../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 "Backup Count"
msgstr "Anzahl an Ersatz"
msgstr "Anzahl an Ersatztunneln"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:368
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:379
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:352
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:371
msgid "0 backup tunnels (0 redundancy, no added resource usage)"
msgstr "0 Backup Tunnel (0 Redundanz, keine zusätzliche Ressourcennutzung)"
msgstr "0 Ersatztunnel (0 Redundanz, keine zusätzliche Ressourcennutzung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:372
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:383
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:356
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:375
msgid "1 backup tunnel each direction (low redundancy, low resource usage)"
msgstr "1 Backup Tunnel in jede Richtung (geringe Redundanz, geringe Ressourcennutzung)"
msgstr "1 Ersatztunnel in jede Richtung (geringe Redundanz, geringe Ressourcennutzung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:376
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:387
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:360
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:379
msgid "2 backup tunnels each direction (medium redundancy, medium resource usage)"
msgstr "2 Backup Tunnel in jede Richtung (mittlere Redundanz, mittlere Ressourcennutzung)"
msgstr "2 Ersatztunnel in jede Richtung (mittlere Redundanz, mittlere Ressourcennutzung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:364
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:383
msgid "3 backup tunnels each direction (high redundancy, high resource usage)"
msgstr "3 Ersatztunnel in jede Richtung (hohe Redundanz, hohe Ressourcennutzung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:373
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:392
msgid "backup tunnels"
msgstr "Ersatztunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:380
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:391
msgid "3 backup tunnels each direction (high redundancy, high resource usage)"
msgstr "3 Backup Tunnel in jede Richtung (hohe Redundanz, hohe Ressourcennutzung)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:399
msgid "Profile"
msgstr "Profil"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:389
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:400
msgid "backup tunnels"
msgstr "Backup Tunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:387
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:406
msgid "interactive connection"
msgstr "Interaktive Verbindung"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:394
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:405
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:391
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:410
msgid "bulk connection (downloads/websites/BT)"
msgstr "Mengenverbindung (Download/Webseiten/BitTorrent)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:393
msgid "Delay Connect"
msgstr "Verbindung verzögern"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:397
msgid "for request/response connections"
msgstr "für Verbindungen mit Anfragen/Antworten"
#: ../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 Optionen"
msgstr "I2CP-Optionen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:396
#: ../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:407
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:416
msgid "Host"
msgstr "Host"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:400
#: ../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:411
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:420
#: ../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 "Port"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:406
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:443
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:413
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:452
msgid "Reduce tunnel quantity when idle"
msgstr "Reduziert die Anzahl an Tunnel im Leerlauf"
msgstr "Anzahl an Tunneln im Leerlauf reduzieren"
#: ../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/editServer_jsp.java:417
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:433
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:445
#: ../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
msgid "Enable"
msgstr "Aktiviert"
msgstr "aktiviert"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:412
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:449
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:419
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:458
msgid "Reduced tunnel count"
msgstr "Reduzierte Tunnel Anzahl"
msgstr "Reduzierte Tunnelanzahl"
#: ../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:453
#: ../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
msgid "Idle minutes"
msgstr "Minuten im Leerlauf"
msgstr "Minuten Inaktivität"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:420
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:427
msgid "Close tunnels when idle"
msgstr "Schliesse Tunnel im Leerlauf"
msgstr "nicht genutzte Tunnel schließen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:426
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:433
msgid "New Keys on Reopen"
msgstr "Neue Schlüssel beim Wiederöffnen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:434
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:441
msgid "Disable"
msgstr "Deaktiviert"
msgstr "deaktiviert"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:440
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:447
msgid "Delay tunnel open until required"
msgstr "Verzörgere den Tunnelaufbau bis er benötigt wird"
msgstr "Aufbau des Tunnela verzögern, bis dieser benötigt wird"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:450
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:457
msgid "Persistent private key"
msgstr "Dauerhafter privater Schlüssel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:456
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:463
msgid "File"
msgstr "Datei"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:460
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:252
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:467
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:235
msgid "Local destination"
msgstr "Lokales Ziel"
msgstr "lokales Ziel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:464
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:471
msgid "(if known)"
msgstr "(falls bekannt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:468
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:489
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:477
msgid "Local Authorization"
msgstr "lokale Autorisation"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:483
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:497
msgid "Username"
msgstr "Benutzername"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:487
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:501
msgid "Password"
msgstr "Passwort"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:491
msgid "Outproxy Authorization"
msgstr "Outproxy Autorisation"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:507
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:498
msgid "Custom options"
msgstr "Eigene Optionen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:472
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:493
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:511
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:502
msgid "NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted."
msgstr "HINWEIS: Falls der Tunnel gerade aktiv ist werden die meisten Änderungen erst nach einem Neustart des Tunnels wirksam."
msgstr "HINWEIS: Falls der Tunnel gerade aktiv ist, werden die meisten Änderungen erst nach einem Neustart des Tunnels wirksam."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:474
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:495
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:513
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:504
msgid "Cancel"
msgstr "Abbrechen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:478
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:499
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:517
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:508
msgid "Delete"
msgstr "Löschen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:480
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:501
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:519
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:510
msgid "Save"
msgstr "Speichern"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:73
msgid "I2P Tunnel Manager - Edit Server Tunnel"
msgstr "I2P Tunnel Manager - Edit Server Tunnel"
msgstr "I2P-Tunnel-Manager - Servertunnel bearbeiten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:93
msgid "Edit server settings"
msgstr "Server Einstellungen ändern"
msgstr "Servereinstellungen ändern"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:101
msgid "New server settings"
msgstr "Neue Server Einstellungen"
msgstr "Neue Servereinstellungen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:214
msgid "Website name"
@@ -472,88 +514,92 @@ msgstr "(für ausgehende Proxies leer lassen)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:223
msgid "Private key file"
msgstr "Private Schlüsseldatei"
msgstr "private Schlüsseldatei"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:262
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:245
msgid "Add to local addressbook"
msgstr "Zum lokalen Adressbuch hinzufügen"
msgstr "zum lokalen Adressbuch hinzufügen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:415
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:252
msgid "Hostname Signature"
msgstr "Signatur des Namens"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:424
msgid "Encrypt Leaseset"
msgstr "verschlüsseltes Leaseset"
msgstr "Leaseset verschlüsseln"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:421
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:430
msgid "Encryption Key"
msgstr "Schlüssel zum verschlüsseln"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:425
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:434
msgid "Generate New Key"
msgstr "Erzeuge neuen Schlüssel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:427
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:436
msgid "Generate"
msgstr "Erzeuge"
msgstr "Erzeugen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:429
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:487
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:438
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:496
msgid "(Tunnel must be stopped first)"
msgstr "(Tunnel muß zuerst beendet sein)"
msgstr "(Tunnel muss zuerst beendet sein)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:431
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:440
msgid "Restricted Access List"
msgstr "Liste zum beschränktem Zugang"
msgstr "Zugang beschränken"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:437
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:446
msgid "Access List"
msgstr "Zugangsliste"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:441
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:450
msgid "(Restrict to these clients only)"
msgstr "(Beschränkt auf nur diese Klienten)"
msgstr "(Zugang wird auf diese Klienten beschränkt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:457
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:466
msgid "New Certificate type"
msgstr "Neuer Zertifizierungstyp"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:459
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:468
msgid "None"
msgstr "Keinen"
msgstr "Keiner"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:463
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:472
msgid "Hashcash (effort)"
msgstr "Hashcash (Durchsatz)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:469
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:478
msgid "Hashcash Calc Time"
msgstr "Hashcash Berechnungszeit"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:471
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:480
msgid "Estimate"
msgstr "Abschätzung"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:473
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:482
msgid "Hidden"
msgstr "Versteckt"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:477
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:486
msgid "Signed (signed by)"
msgstr "Signiert (unterschrieben von)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:483
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:492
msgid "Modify Certificate"
msgstr "Zertifikat modifizieren"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:485
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:494
msgid "Modify"
msgstr "Modifizieren"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:71
msgid "I2P Tunnel Manager - List"
msgstr "I2P Tunnel Manager - List"
msgstr "I2P-Tunnel-Manager - Liste"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:83
msgid "Status Messages"
msgstr "Status Nachrichten"
msgstr "Statusnachrichten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:87
msgid "Refresh"
@@ -561,11 +607,11 @@ msgstr "Auffrischen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:91
msgid "Stop All"
msgstr "Alle Stoppen"
msgstr "Alle stoppen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:95
msgid "Start All"
msgstr "Alle Starten"
msgstr "Alle starten"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:99
msgid "Restart All"
@@ -577,12 +623,12 @@ msgstr "Konfiguration neu einlesen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:105
msgid "I2P Server Tunnels"
msgstr "I2P Server Tunnel"
msgstr "I2P-Servertunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:109
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:130
msgid "Points at"
msgstr "Zeigt auf"
msgstr "Läuft auf"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:111
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:153
@@ -599,7 +645,7 @@ msgstr "Status"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:163
msgid "Base32 Address"
msgstr "Basis-32 Adresse"
msgstr "Basis-32-Adresse"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:171
msgid "No Preview"
@@ -608,7 +654,7 @@ msgstr "Keine Vorschau"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:184
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:285
msgid "Starting..."
msgstr "Starte..."
msgstr "Starte ..."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:191
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:205
@@ -616,7 +662,7 @@ msgstr "Starte..."
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:306
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:320
msgid "Stop"
msgstr "Stop"
msgstr "Stopp"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:198
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:313
@@ -638,18 +684,18 @@ msgid "New server tunnel"
msgstr "Neuer Servertunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:236
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:368
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:377
msgid "Standard"
msgstr "Standard"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:238
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:370
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:379
msgid "Create"
msgstr "Erstelle"
msgstr "Erstellen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:240
msgid "I2P Client Tunnels"
msgstr "I2P Klienten Tunnel"
msgstr "I2P-Klienten-Tunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:248
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:274
@@ -660,15 +706,19 @@ msgstr "Interface"
msgid "Standby"
msgstr "Wartestellung"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:346
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:344
msgid "Outproxy"
msgstr "Ausgehender Proxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:350
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:348
msgid "Destination"
msgstr "Ziel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:366
msgid "New client tunnel"
msgstr "Neuer Klienten Tunnel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:362
msgid "none"
msgstr "Keiner"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:375
msgid "New client tunnel"
msgstr "Neuer Kliententunnel"

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-07-04 16:39+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,71 +17,113 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Dutch\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:492
#: ../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 "Om de destination in je host database te bezoeken, klik <a href=\"{0}\">here</a>. Om de conflicterende adreshelper destination te bezoeken, klik <a href=\"{1}\">here</a>."
msgstr ""
"Om de destination in je host database te bezoeken, klik <a href=\"{0}"
"\">hier</a>. Om de conflicterende adreshelper destination te bezoeken, klik "
"<a href=\"{1}\">hier</a>."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:909
#: ../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:"
msgstr ""
"Klik op een onderstaande link om te zoeken naar een adreshelper via een "
"\"jump\" service:"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:372
#: ../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' "
"button on your browser. Please resubmit."
msgstr ""
"Ongeldige formulier verzonden, waarschijnlijk doordat je de 'back' of "
"'reload' button van je browser hebt gebruikt. Verzend opnieuw."
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:217
msgid "Configuration reloaded for all tunnels"
msgstr "Configuratie van alle tunnels opnieuw geladen"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:229
msgid "Starting tunnel"
msgstr "Opstarten van tunnel"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:242
msgid "Stopping tunnel"
msgstr "Stoppen van tunnel"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:389
msgid "New Tunnel"
msgstr "Nieuwe Tunnel"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:392
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:409
msgid "Standard client"
msgstr "Standaard client"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:393
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:410
msgid "HTTP client"
msgstr "HTTP client"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:394
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:411
msgid "IRC client"
msgstr "IRC client"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:395
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:412
msgid "Standard server"
msgstr "Standaard server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:396
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:413
msgid "HTTP server"
msgstr "HTTP server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:397
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:414
msgid "SOCKS 4/4a/5 proxy"
msgstr "SOCKS 4/4a/5 proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:398
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:415
msgid "SOCKS IRC proxy"
msgstr "SOCKS IRC proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:399
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:416
msgid "CONNECT/SSL/HTTPS proxy"
msgstr "CONNECT/SSL/HTTPS proxy"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:400
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:417
msgid "IRC server"
msgstr "IRC server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:401
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:418
msgid "Streamr client"
msgstr "Streamr client"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:402
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:419
msgid "Streamr server"
msgstr "Streamr server"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:403
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:420
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"
@@ -106,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:358
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:386
msgid "Description"
msgstr "Omschrijving"
@@ -124,345 +166,371 @@ 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:220
#: ../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:208
msgid "Shared Client"
msgstr "Gedeelde Client"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:224
#: ../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 "(Deel tunnels met andere clients en irc/httpclients? Wijziging vereist herstart van de client proxy)"
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:228
#: ../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:232
#: ../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:234
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:249
#: ../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:236
#: ../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 "(OPMERKING: wanneer deze client proxy is geconfigureerd om tunnels te delen, dan zijn deze opties van toepassing voor alle gedeelde proxy clients!)"
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:238
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:251
#: ../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:240
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:253
#: ../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:247
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:260
#: ../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:251
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:264
#: ../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:255
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:268
#: ../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:259
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:272
#: ../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:268
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281
#: ../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:273
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:286
#: ../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:280
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:293
#: ../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:284
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:297
#: ../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)"
msgstr ""
"+ 0-1 hop variantie (gemiddeld toegevoegde randomisatie, minder prestatie)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:288
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:301
#: ../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:292
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:305
#: ../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:296
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:309
#: ../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:308
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:321
#: ../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:313
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:326
#: ../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:320
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:333
#: ../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)"
msgstr ""
"1 inkomende, 1 uitgaande tunnel (laag bandbreedte gebruik, minder "
"betrouwbaar)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:324
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:337
#: ../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 inkomende, 2 uitgaande tunnels (standaard bandbreedte gebruik, standaard betrouwbaarheid)"
msgstr ""
"2 inkomende, 2 uitgaande tunnels (standaard bandbreedte gebruik, standaard "
"betrouwbaarheid)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:328
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:341
#: ../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)"
msgstr ""
"3 inkomende, 3 uitgaande tunnels (hoge bandbreedte gebruik, hogere "
"betrouwbaarheid)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:337
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:350
#: ../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:342
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:355
#: ../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:349
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:362
#: ../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:353
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:366
#: ../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)"
msgstr ""
"1 backup tunnel in beide richting (lage redundantie, lage aantal bronnen "
"gebruikt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:357
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:370
#: ../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)"
msgstr ""
"2 backup tunnels in beide richting (gemiddelde redundantie, gemiddeld aantal "
"bronnen gebruikt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:361
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:374
#: ../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)"
msgstr ""
"3 backup tunnels in beide richting (hoge redundantie, hoog aantal bronnen "
"gebruikt)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:370
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:383
#: ../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:377
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:390
#: ../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:384
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:397
#: ../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:388
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:401
#: ../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:390
#: ../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:394
#: ../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:398
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:405
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:400
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:146
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:407
#: ../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:404
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:152
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:411
#: ../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:410
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:443
#: ../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:412
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:426
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:434
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:446
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:456
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:417
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:433
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:445
#: ../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:416
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:449
#: ../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:420
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:440
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:453
#: ../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:424
#: ../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:430
#: ../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:438
#: ../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:444
#: ../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:454
#: ../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:460
#: ../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:464
#: ../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:468
#: ../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:472
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:489
#: ../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: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: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:484
msgid "Outproxy Authorization"
msgstr "Uitgaande Proxy Autorisatie"
#: ../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:476
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:493
#: ../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 "OPMERKING: Indien de tunnel op dit moment draait, zullen de meeste wijzigingen pas effect hebben na het stoppen en herstarten van de tunnel."
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:478
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:495
#: ../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:482
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:499
#: ../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:484
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:501
#: ../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"
@@ -478,88 +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:415
#: ../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:417
msgid "Encrypt Leaseset"
msgstr "Versleutel Leaseset"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:421
#: ../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:425
#: ../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:427
#: ../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:429
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:487
#: ../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:431
#: ../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:437
#: ../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:441
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:457
#: ../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:459
#: ../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:463
#: ../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:469
#: ../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:471
#: ../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:473
#: ../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:477
#: ../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:483
#: ../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:485
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:521
msgid "Modify"
msgstr "Wijzig"
@@ -609,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"
@@ -622,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"
@@ -654,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:368
#: ../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:370
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:398
msgid "Create"
msgstr "Creëer"
@@ -668,22 +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:346
#: ../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:350
#: ../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:366
#: ../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:394
msgid "New client tunnel"
msgstr "Nieuwe client tunnel"

View File

@@ -8,76 +8,109 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-03-06 00:05+0000\n"
"PO-Revision-Date: 2010-03-06 00:08+0000\n"
"Last-Translator: 4get <forget@mail.i2p>\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Russian\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:483
#: ../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:886
#: ../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/IndexBean.java:363
#: ../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 "Неправильно переданная форма, возможно вы использовали действие браузера \"назад\" или \"обновить\". Пожалуйста повторите попытку."
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:217
msgid "Configuration reloaded for all tunnels"
msgstr "Конфигурация для всех туннелей перечитана"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:229
msgid "Starting tunnel"
msgstr "Запуск туннеля"
#. and give them something to look at in any case
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:242
msgid "Stopping tunnel"
msgstr "Остановка туннеля"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:389
msgid "New Tunnel"
msgstr "Новый туннель"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:383
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:409
msgid "Standard client"
msgstr "Обычный клиент"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:384
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:410
msgid "HTTP client"
msgstr "HTTP-клиент"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:385
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:411
msgid "IRC client"
msgstr "IRC-клиент"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:386
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:412
msgid "Standard server"
msgstr "Обычный сервер"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:387
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:413
msgid "HTTP server"
msgstr "HTTP-сервер"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:388
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:414
msgid "SOCKS 4/4a/5 proxy"
msgstr "SOCKS 4/4a/5 прокси"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:389
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:415
msgid "SOCKS IRC proxy"
msgstr "SOCKS IRC прокси"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:390
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:416
msgid "CONNECT/SSL/HTTPS proxy"
msgstr "CONNECT/SSL/HTTPS прокси"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:391
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:417
msgid "IRC server"
msgstr "IRC-сервер"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:392
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:418
msgid "Streamr client"
msgstr "Streamr-клиент"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:393
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:419
msgid "Streamr server"
msgstr "Streamr-сервер"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:394
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:420
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 — Редактирование Клиентского Туннеля"
@@ -102,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:358
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:386
msgid "Description"
msgstr "Описание"
@@ -120,253 +153,236 @@ 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:220
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:237
msgid "Profile"
msgstr "Режим"
#: ../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:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:244
msgid "interactive connection"
msgstr "оптимизировать для малых задержек (irc)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:231
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:248
msgid "bulk connection (downloads/websites/BT)"
msgstr "оптимизировать для большого обьема (www/bittorrent)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:233
msgid "Delay Connect"
msgstr "Задержка соединения"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:237
msgid "for request/response connections"
msgstr "оптимизация для соединений, начинающихся с запроса клиента/ответа сервера"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239
#: ../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:243
#: ../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:247
#: ../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:251
#: ../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:253
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:266
#: ../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:255
#: ../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:257
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:268
#: ../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:259
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:270
#: ../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:266
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:277
#: ../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:270
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281
#: ../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:274
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:285
#: ../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:278
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:289
#: ../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:287
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:298
#: ../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:292
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:303
#: ../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:299
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:310
#: ../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:303
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:314
#: ../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:307
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:318
#: ../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:311
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:322
#: ../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:315
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:326
#: ../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:327
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:338
#: ../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:332
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:343
#: ../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:339
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:350
#: ../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:343
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:354
#: ../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:347
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:358
#: ../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:356
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:367
#: ../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:361
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:372
#: ../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:368
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:379
#: ../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:372
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:383
#: ../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:376
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:387
#: ../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:380
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:391
#: ../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:389
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:400
#: ../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:394
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:405
msgid "I2CP Options"
msgstr "Параметры I2CP"
#: ../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:396
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:146
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:407
#: ../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: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:378
msgid "Delay Connect"
msgstr "Задержка соединения"
#: ../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: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: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:400
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:152
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:411
#: ../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:406
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:445
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:479
msgid "Reduce tunnel quantity when idle"
msgstr "Снижать количество туннелей при простое"
@@ -375,20 +391,21 @@ msgstr "Снижать количество туннелей при просто
#: ../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/editServer_jsp.java:417
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:435
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:447
#: ../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:412
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:451
#: ../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:416
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:436
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:455
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:489
msgid "Idle minutes"
msgstr "Минут простоя"
@@ -401,6 +418,7 @@ msgid "New Keys on Reopen"
msgstr "Генерировать новый ключ при переоткрытии"
#: ../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 "Выключить"
@@ -417,7 +435,7 @@ msgid "File"
msgstr "Файл"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:460
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:252
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:220
msgid "Local destination"
msgstr "Локальный адрес назначения"
@@ -425,30 +443,52 @@ msgstr "Локальный адрес назначения"
msgid "(if known)"
msgstr "(если известен)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:468
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:491
#: ../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: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: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:484
msgid "Outproxy Authorization"
msgstr "Авторизация outproxy"
#: ../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:472
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:495
#: ../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:474
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:497
msgid "Save"
msgstr "Сохранить"
#: ../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:478
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:501
#: ../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:480
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:503
msgid "Cancel"
msgstr "Отмена"
#: ../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 "Сохранить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:73
msgid "I2P Tunnel Manager - Edit Server Tunnel"
@@ -462,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:262
#: ../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:415
#: ../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:417
msgid "Encrypt Leaseset"
msgstr "Шифровать LeaseSet"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:421
#: ../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:425
#: ../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:427
#: ../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:429
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:489
#: ../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:431
#: ../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:433
msgid "Unimplemented"
msgstr "не реализовано"
#: ../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:443
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: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:461
#: ../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:465
#: ../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:471
#: ../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:473
#: ../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:475
#: ../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:479
#: ../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:485
#: ../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:487
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:521
msgid "Modify"
msgstr "Изменить"
@@ -597,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 "Состояние"
@@ -610,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 "Запустить"
@@ -642,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:368
#: ../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:370
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:398
msgid "Create"
msgstr "Создать"
@@ -656,24 +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:346
#: ../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:350
#: ../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:366
#: ../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: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

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-07-01 04:52+0000\n"
"POT-Creation-Date: 2010-10-04 02:45+0000\n"
"PO-Revision-Date: 2010-05-29 10:57+0800\n"
"Last-Translator: walking <walking@mail.i2p>\n"
"Language-Team: foo <foo@bar>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Chinese\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:493
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:492
#, java-format
msgid ""
"To visit the destination in your host database, click <a href=\"{0}\">here</"
@@ -35,55 +35,55 @@ msgstr ""
"请点击下面的链接通过【跳转(Jump)】服务提供的【地址助手】链接跳转至域名对应的"
"主机:"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:369
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:372
msgid "New Tunnel"
msgstr "新建隧道"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:389
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:392
msgid "Standard client"
msgstr "标准客户端"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:390
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:393
msgid "HTTP client"
msgstr "HTTP 客户端"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:391
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:394
msgid "IRC client"
msgstr "IRC 客户端"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:392
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:395
msgid "Standard server"
msgstr "标准服务器"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:393
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:396
msgid "HTTP server"
msgstr "HTTP 服务器"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:394
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:397
msgid "SOCKS 4/4a/5 proxy"
msgstr "SOCKS4/4A/5 代理"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:395
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:398
msgid "SOCKS IRC proxy"
msgstr "SOCKS IRC 代理"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:396
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:399
msgid "CONNECT/SSL/HTTPS proxy"
msgstr "CONNECT/SSL/HTTPS 代理"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:397
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:400
msgid "IRC server"
msgstr "IRC 服务器"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:398
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:401
msgid "Streamr client"
msgstr "Streamr 客户端"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:399
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:402
msgid "Streamr server"
msgstr "Streamr 服务器"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:400
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:403
msgid "HTTP bidir"
msgstr "双向http"

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();
}
}

View File

@@ -392,7 +392,7 @@ public abstract class Resource implements Serializable
buf.append(path);
buf.append("\">");
buf.append(StringUtil.replace(StringUtil.replace(ls[i],"<","&lt;"),">","&gt;"));
buf.append("&nbsp;");
buf.append("</A>&nbsp;");
buf.append("</TD><TD ALIGN=right>");
buf.append(item.length());
buf.append(" bytes&nbsp;</TD><TD>");

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
<target name="all" depends="clean, build" />
<target name="build" depends="builddep, jar" />
<target name="builddep">
<ant dir="../../../core/java/" target="build" />
<!-- run from top level build.xml to get dependencies built -->
</target>
<condition property="depend.available">
<typefound name="depend" />
@@ -45,9 +45,7 @@
<delete dir="./build" />
</target>
<target name="cleandep" depends="clean">
<ant dir="../../../core/java/" target="cleandep" />
</target>
<target name="distclean" depends="clean">
<ant dir="../../../core/java/" target="distclean" />
</target>
</project>

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

@@ -45,6 +45,10 @@ public class I2PSocketEepGet extends EepGet {
/** this replaces _proxy in the superclass. Sadly, I2PSocket does not extend Socket. */
private I2PSocket _socket;
/** from ConnectionOptions */
private static final String PROP_CONNECT_DELAY = "i2p.streaming.connectDelay";
private static final String CONNECT_DELAY = "500";
public I2PSocketEepGet(I2PAppContext ctx, I2PSocketManager mgr, int numRetries, String outputFile, String url) {
this(ctx, mgr, numRetries, -1, -1, outputFile, null, url);
}
@@ -123,6 +127,10 @@ public class I2PSocketEepGet extends EepGet {
Properties props = new Properties();
props.setProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT, "" + CONNECT_TIMEOUT);
props.setProperty(I2PSocketOptions.PROP_READ_TIMEOUT, "" + INACTIVITY_TIMEOUT);
// This is important - even if the underlying socket doesn't have a connect delay,
// we want to set it for this connection, so the request headers will go out
// in the SYN packet, saving one RTT.
props.setProperty(PROP_CONNECT_DELAY, CONNECT_DELAY);
I2PSocketOptions opts = _socketManager.buildOptions(props);
_socket = _socketManager.connect(dest, opts);
} else {

View File

@@ -130,16 +130,19 @@ public class I2PSocketManagerFactory {
if (!opts.containsKey(name))
opts.setProperty(name, System.getProperty(name));
}
boolean oldLib = DEFAULT_MANAGER.equals(opts.getProperty(PROP_MANAGER, DEFAULT_MANAGER));
if (oldLib && false) {
//boolean oldLib = DEFAULT_MANAGER.equals(opts.getProperty(PROP_MANAGER, DEFAULT_MANAGER));
//if (oldLib && false) {
// for the old streaming lib
opts.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_GUARANTEED);
// opts.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_GUARANTEED);
//opts.setProperty("tunnels.depthInbound", "0");
} else {
//} else {
// for new streaming lib:
opts.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT);
//opts.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT);
// as of 0.8.1 (I2CP default is BestEffort)
if (!opts.containsKey(I2PClient.PROP_RELIABILITY))
opts.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
//p.setProperty("tunnels.depthInbound", "0");
}
//}
if (i2cpHost != null)
opts.setProperty(I2PClient.PROP_TCP_HOST, i2cpHost);

View File

@@ -6,7 +6,7 @@ import java.util.Properties;
* Define the configuration for streaming and verifying data on the socket.
*
*/
public class I2PSocketOptionsImpl implements I2PSocketOptions {
class I2PSocketOptionsImpl implements I2PSocketOptions {
private long _connectTimeout;
private long _readTimeout;
private long _writeTimeout;

View File

@@ -3,12 +3,10 @@
<target name="all" depends="clean, build" />
<target name="build" depends="builddep, jar" />
<target name="builddep">
<ant dir="../../../router/java/" target="build" />
<ant dir="../../systray/java/" target="build" />
<!-- router will build core -->
<!-- run from top level build.xml to get dependencies built -->
</target>
<target name="prepare">
<ant dir="../../jetty/" target="build" />
<!-- run from top level build.xml to get dependencies built -->
</target>
<condition property="depend.available">
<typefound name="depend" />
@@ -92,6 +90,7 @@
<!-- jar again to get the latest messages_*.class files -->
<jar destfile="./build/routerconsole.jar" basedir="./build/obj" includes="**/*.class" update="true" />
</target>
<target name="poupdate" depends="build">
<ant target="war" />
<!-- Update the messages_*.po files.
@@ -113,7 +112,7 @@
<target name="war" depends="precompilejsp">
<!-- Don't include the css in the war, the main build.xml will copy it to docs/themes/console/ -->
<war destfile="build/routerconsole.war" webxml="../jsp/web-out.xml"
basedir="../jsp/" excludes="web.xml, *.css, **/*.java, *.jsp, *.jsi, web-fragment.xml">
basedir="../jsp/" excludes="web.xml, *.css, **/*.java, *.jsp, *.jsi, web-fragment.xml, web-out.xml">
</war>
</target>
<target name="precompilejsp" unless="precompilejsp.uptodate">
@@ -234,13 +233,7 @@
<delete file="../jsp/web-out.xml" />
</target>
<target name="cleandep" depends="clean">
<!-- router will clean core -->
<ant dir="../../../router/java/" target="cleandep" />
<ant dir="../../systray/java/" target="cleandep" />
</target>
<target name="distclean" depends="clean">
<!-- router will clean core -->
<ant dir="../../../router/java/" target="distclean" />
<ant dir="../../systray/java/" target="distclean" />
</target>
</project>

View File

@@ -32,8 +32,9 @@ then
sed 's/..,\(..*\)/_("\1");/' $CFILE >> $JFILE
fi
# list specific files in router/ here, so we don't scan the whole tree
# list specific files in core/ and router/ here, so we don't scan the whole tree
ROUTERFILES="\
../../../core/java/src/net/i2p/data/DataHelper.java \
../../../router/java/src/net/i2p/router/RouterThrottleImpl.java \
../../../router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java \
../../../router/java/src/net/i2p/router/transport/TransportManager.java \

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) {

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