Compare commits

..

474 Commits

Author SHA1 Message Date
zzz
abd96a920f 0.7.11 2010-02-15 12:43:28 +00:00
51a1564566 Fix addWebApplications API goofup, Bump BOB version, which I forgot to do. 2010-02-13 13:46:10 +00:00
zzz
bd068058c3 * Floodfills: Increase max to 28 (was 15) and min to 20 (was 10) 2010-02-13 12:02:33 +00:00
4591f77928 A few minor updates 2010-02-13 10:51:00 +00:00
6d67848096 org.mortbay.jetty.Server modified method to accept Attributes for batch webapp launches via addWebApplications(). 2010-02-12 22:15:59 +00:00
zzz
c145ed103a merge of '5a88275dbd49dfde016676939fb28b1387447216'
and 'b4afc02ff8ecaf95f621169763cfa99e3f309102'
2010-02-11 23:02:03 +00:00
2b4b47eff6 Russian translation updated (readonly install directory message) 2010-02-10 20:30:51 +00:00
zzz
04ae0e2610 * I2PTunnelRunner: Flush initial data, for some reason it wasn't
getting flushed ever in some cases.
2010-02-10 20:17:31 +00:00
zzz
0e853a3119 fix missing readme files in debian 2010-02-10 13:45:31 +00:00
zzz
a0cad7e8e9 -10 2010-02-10 12:58:45 +00:00
zzz
05d22344b5 * Izpack: Add 64-bit windows dll so installer doesn't die trying to add shortcuts 2010-02-10 11:49:21 +00:00
zzz
7212f855d8 Upgrade to launch4j 3.0.1 2008-07-20.
The license is BSD for launch4j and MIT for the wrapper code in head/

Changelog is in installer/lib/launch4j/web/changelog.html
Hopefully this will fix installs for 64-bit JRE on 64-bit windows.

The previous version was 2.0-RC3 2005-08-13.
The previous license was GPLv2 for launch4j and LGPLv2.1 for the wrapper code in head/

The bin/ld.exe and bin/windres.exe files were contributed by
i2p users in 2005 so the i2p installer could be built on windows.

They have not been updated for 3.0.1, so pkg builds on windows
will presumably still get 2.0-RC3.
2010-02-09 17:21:48 +00:00
zzz
d7e90969d0 delete jettylib on distclean to ensure we get the new jetty 2010-02-07 20:16:18 +00:00
zzz
2a99e2a295 -9 2010-02-06 18:55:11 +00:00
zzz
49fae646e2 merge of '9e658a1b1e62b486a399a162ceb27fe3461a9eb0'
and 'fe3561146f8172bdb86292eade40a031b7dee4fb'
2010-02-06 18:53:18 +00:00
d0d062b6f4 No more port 8887 in de troubleshoot 2010-02-06 16:52:16 +00:00
zzz
7b59ceb4ae Add transmission ID 2010-02-05 20:02:23 +00:00
zzz
7c236c0fa0 Console: Fix saving update keys, was broken in 0.7.10 2010-02-05 19:18:26 +00:00
zzz
7a7e650ca0 news.xml: Wrap i2p version tags in XML comment 2010-02-05 19:18:06 +00:00
zzz
7a32f8efd6 Try yet again to prevent two NTCP pumpers 2010-02-05 19:17:46 +00:00
zzz
101135a99a fix sending of stopped events to the tracker 2010-02-04 14:47:15 +00:00
zzz
746c1bd628 * NetDb: Lower min RouterInfo expiration to 2.5h (was 3h)
* i2psnark debug logging tweak
2010-02-03 14:21:55 +00:00
zzz
6801fc667a - Hide update buttons and update config if install dir is readonly or if configured 2010-02-02 15:25:26 +00:00
zzz
794db19b6d javadoc 2010-02-02 15:19:17 +00:00
zzz
d4637818be - Show yellow star if no outbound tunnels 2010-02-02 15:18:22 +00:00
zzz
33b7dca782 * i2psnark: Don't prefer to opportunistically unchoke unchoking peers when not interested 2010-02-02 15:14:44 +00:00
zzz
bfd1306a56 fix for missing tgz build error 2010-01-31 20:26:57 +00:00
zzz
ed443fe0d6 jetty 5.1.15 2010-01-31 05:06:50 +00:00
390981e10c Fix NPE in TCPtoI2P when a lookup fails, report the error to the stream.
Fix setkeys bug in DoCMDS, forgot to create the object before calling t's methods, which threw an NPE.
2010-01-30 05:26:30 +00:00
zzz
f86f2701ff - Speed up some hashcode() and equals()
- Cleanup and javadoc
2010-01-29 13:57:57 +00:00
zzz
63d3685652 * Jetty: Turn on checkAliases 2010-01-29 13:55:16 +00:00
zzz
0a93466999 - Add basic DOS prevention for lookups
- Move flood throttle check so we don't throttle ourselves
2010-01-29 13:53:14 +00:00
zzz
81664bc776 - Don't update unused lease fail stats 2010-01-29 13:47:50 +00:00
zzz
6d60a6f833 - Don't store over client tunnels to pre-0.7.10 floodfills 2010-01-29 13:42:42 +00:00
zzz
4186894a39 * build.xml: Add a debian-source target
* Startup: Disable browser launch for debian daemon
2010-01-29 13:41:40 +00:00
cfeafacd07 update the pos 2010-01-29 09:26:02 +00:00
dev
9c2edf5c6a update history 2010-01-28 20:06:16 +00:00
dev
72396f0f96 merge of '3679ca64eea825719eb0d26b285091a9e81107f3'
and '36fc8877438b0f8fa6220cd52459497af5a2eed6'
2010-01-28 20:05:12 +00:00
dev
45388b0d48 added an getTargetAddresses(transportStyle) method to the RouterInfo structure 2010-01-28 20:05:03 +00:00
zzz
a8ae36c403 fixup 2010-01-26 20:05:03 +00:00
zzz
164b39d8df * I2NP: Various cleanup and bulletproofing 2010-01-26 19:59:39 +00:00
zzz
ccc95087a1 shrink the stats.jsp dropdown 2010-01-26 19:56:36 +00:00
zzz
b97f4f8bd7 try to silence log errors at shutdown 2010-01-26 19:53:25 +00:00
zzz
76c1f47b20 * Profiles: Fix lack of profiles at router startup, especially for new routers 2010-01-26 19:52:06 +00:00
zzz
ce74e49236 * Clock: Don't refuse to update because of peer skew the first time 2010-01-26 19:49:35 +00:00
zzz
977d39aeb1 minor license updates 2010-01-26 19:49:21 +00:00
zzz
a821ea2752 take non-linux stuff out of debian jbigi.jar 2010-01-26 16:25:03 +00:00
zzz
b97197c0fa * Debian: Fixup, update, enhance dream's scripts
* build.xml: Speed up sponge's distclean additions
2010-01-26 15:21:41 +00:00
zzz
474691927a fix date 2010-01-24 15:41:33 +00:00
zzz
81dcbedd17 * Transport clock skews:
- Store and report UDP clock skews even for large values, so
        a badly skewed local clock will be reported to the console
      - Don't shitlist for NTCP clock skew if we don't know what time it is
      - If NTP hasn't worked yet, have NTCP or SSU update the clock one time
      - Include failed clock skew in NTCP skew vector if there aren't many connections
      - Don't include NTCP clock skews for non-established connections
      - Fix framed clock skew frame size
      - Report framed clock skew even if for only one peer, if NTP hasn't worked yet
      - Don't log RRD errors after clock adjustment
      - Reduce min skew for console warning to 30s (was 45s)
      - More Java 5 cleanups
2010-01-24 15:38:44 +00:00
zzz
4f5cfdee57 adjust welt reseed hostname 2010-01-24 15:35:02 +00:00
zzz
2c7725a8e4 cleanups 2010-01-24 15:34:40 +00:00
zzz
0ba6482da5 -1 2010-01-24 02:42:06 +00:00
zzz
4c1fd67925 propagate from branch 'i2p.i2p.zzz.test' (head 9b243b031d937eaefcd4c15ae61bb4fa280d78f3)
to branch 'i2p.i2p' (head 9383c447b12abf45f80bd0059f719acfce4c70a3)
2010-01-24 02:37:55 +00:00
zzz
25683cc0de merge of '338745763da1ce77c8adc9f889449dc14451f3fb'
and 'ba40565ead71f8ce02500978ca95ca90340a294d'
2010-01-24 02:37:21 +00:00
zzz
087fd5a909 * NetDb:
- Move stat initialization, reduce number of rates
      - Add basic DOS prevention by not flooding if stores are too-frequent
2010-01-24 02:36:42 +00:00
zzz
fdfbab850a minor cleanups 2010-01-24 02:16:36 +00:00
zzz
f1c50b7fc3 * Clock:
- Don't let a client update the router clock
      - Restore and enhance vanished clock error log message
2010-01-24 02:14:39 +00:00
zzz
959bf4a7f4 limit max graph size 2010-01-24 02:11:55 +00:00
zzz
5dda915467 * Startup:
- Enable multiple parallel job runners much sooner to speed startup
      - Rearrange the startup order to get the long jobs started sooner
      - Don't allow the netDb readin job to clog the job queue
2010-01-23 19:12:37 +00:00
zzz
66d8fd6c2a * ProfileOrganizer:
- Limit High Cap to 75 max
      - Reduce max lock wait time
      - More cleanup
2010-01-23 03:40:56 +00:00
06efe306c3 Deutsch eepsite help text updated to the latest version by zzz (October'2009). Fixed i2host.i2p url typo. 2010-01-22 17:04:59 +00:00
dev
15d1b005f5 merge of '120e01fdee48c2f8652e8314f3dcfb5655a3b7b1'
and 'e30d2f11dde010812b8a5607e5407e37d745700d'
2010-01-22 15:27:01 +00:00
zzz
7efab75c3c 0.7.10 2010-01-21 19:44:49 +00:00
zzz
a9e4248c93 Increase ff count; -6 2010-01-21 14:22:32 +00:00
zzz
5338dc5540 * Properties: Don't play games with \r and \n on load/save,
it was causing fatal issues on DOS if your username started
      with r or n
2010-01-21 14:19:38 +00:00
zzz
09d3dc8e90 * Logs: Don't be quite so noisy in the wrapper log if we
can't open the router log
2010-01-21 14:18:31 +00:00
zzz
3bf95e566c * I2PTunnelServer: Fix bug preventing connection retries
at startup from working
2010-01-21 14:17:37 +00:00
zzz
958a5a3c4e * eepget.bat: Add to pkg 2010-01-21 14:17:10 +00:00
7b48f6387f build.xml tweaks for batch copying the eepsite.help 2010-01-21 13:22:15 +00:00
fcd2cdb136 merge of '4755aa75bada4925580e70471d2cbe82d52f4e1e'
and 'af16732f69734b702b887071df3348e77d3c7c97'
2010-01-21 12:15:43 +00:00
6b59356bc5 disapproval of revision 'df747c3515cd167431e6e003a732943e35aef79d' 2010-01-21 12:14:11 +00:00
z3d
1c7f098d9b Add missing index_na.html to our eepsite stash. 2010-01-21 11:46:52 +00:00
103c15f000 Russian translation updated to dr|z3d's template, links to the Russian page moved to the alphabetically sorted position 2010-01-21 08:53:31 +00:00
0fd55f8b07 Added: missing non-translated welcome page from dr|z3d's template. 2010-01-21 08:50:54 +00:00
511c1e7b9d Re-added: docroot location on Windows (from October'2009 version by zzz) 2010-01-21 08:50:36 +00:00
z3d
7df3bde2ce Add Russian to the eepsite index; prettify the Russian index with the new css. Minor tweaks to the css. 2010-01-21 08:18:55 +00:00
z3d
25e6b6e6c4 Add a note to history.txt re eespite changes. 2010-01-21 08:00:37 +00:00
z3d
cb81f2c9ba Updated eepsite indexes with the new layout + pagetemplate.html 2010-01-21 07:46:03 +00:00
z3d
6c25f0fd16 Build.xml mods to accomodate new eepsite structure. 2010-01-21 07:21:01 +00:00
z3d
934f3d1814 Move robots.txt to eepsite.help dir; add redirecting index.html 2010-01-21 02:52:04 +00:00
z3d
e883fd6b1b Let's mirror the actual eepsite contents in the installer.. 2010-01-21 02:48:49 +00:00
z3d
e3b300e978 Add graphical resources to eepsite. 2010-01-21 02:08:55 +00:00
z3d
03a9f69739 Move Russian eepsite index to our new eepsite.help dir. 2010-01-21 00:49:56 +00:00
z3d
be2dca8ee7 merge of '6dbc656c7ca49810cd09d02d8ddafdc9e083d12e'
and 'efdeefc134243f15d893f98dcbe275657fcc807a'
2010-01-19 11:38:49 +00:00
5c595ef289 * Firewall fix for NTCP, where firewalls will forget a NAT relationship
on a stream... AKA setting keepalive. This should fix the stuck NTCP
      issue that has been bothing zzz for years.
    * Set keepalive on BOB connections too, since this will assist closing
      the connections in the event of a crash on a client.
2010-01-19 08:54:40 +00:00
z3d
d9534e5f23 First stage of eepsite starter page rejig. 2010-01-18 21:13:29 +00:00
00fa3806d8 Russian translation update (Share ratio, HTTP bidir, Add Client, ...) 2010-01-18 19:28:32 +00:00
6c5ef9acdc Added: Russian translation 2010-01-18 19:27:59 +00:00
zzz
2db5914ba0 Save graph settings when changed 2010-01-18 17:39:12 +00:00
zzz
35a0dafb83 * Reseed: Support SSL and proxies 2010-01-18 15:42:50 +00:00
zzz
5f12688a90 * Console: Add a tunnel share ratio estimate 2010-01-18 14:57:03 +00:00
zzz
f8d9af871a javadoc 2010-01-18 14:54:59 +00:00
zzz
08a2b4bbf0 * graphs.jsp: Remove jrobin sig, set lower limit to 0 2010-01-18 14:54:32 +00:00
zzz
27a5793fd0 * configclients.jsp: Fix add-new-client feature
* Translate: Catch empty string
2010-01-18 14:51:39 +00:00
b1151f82b5 Messages_fr.po update 2010-01-17 21:11:20 +00:00
zzz
b6332f8313 history for prop, -3 2010-01-17 13:50:16 +00:00
zzz
e036cd4332 propagate from branch 'i2p.i2p.zzz.test' (head dc29b32afe515f704985a4f92cda6e28a65ccdc5)
to branch 'i2p.i2p' (head fb38016f22528778128e22269b8f256c8c640466)
2010-01-17 13:42:33 +00:00
zzz
174fedc2e6 - Flood even if the entry was received via a garlic message
- Encrypt stores only if floodfill supports it
2010-01-17 02:45:55 +00:00
zzz
4803e60db4 Limit fast tier to 30 max 2010-01-16 23:23:58 +00:00
zzz
abb62b93e3 store to a different ff after verify fail 2010-01-16 18:59:00 +00:00
zzz
95bb322cd7 Clock: Change a CRIT to an ERROR, lower threshold for changing from 10s to 5s 2010-01-16 18:58:02 +00:00
zzz
670b4033cb Add a small number of ms (0-300) that increases as we approach the expire time.
Since the earliest date functions as a version number,
this will force the floodfill to flood each new version;
otherwise it won't if the earliest time hasn't changed.
2010-01-16 17:06:20 +00:00
zzz
715ae13997 dont log a RI DSM down a client tunnel as an error, just silently drop, as probably the result of a FVSJ 2010-01-16 17:06:01 +00:00
zzz
77b88ab59d * NetDb Stores and Verifies:
- Do LS stores and verifies through client tunnels
        to prevent correlation by the OBEP or FF
      - Encrypt LS stores to prevent snooping by the OBEP
      - Encrypt LS and RI verifies to prevent snooping by the OBEP
      - Extend verify delay and timeout
      - Reenable RI verifies
      - Disallow simultaneous verifies for the same key
      - Don't resend on verify timeout; try a different peer instead
      - Adjust ff selection criteria
2010-01-15 21:37:41 +00:00
zzz
64235bd745 * NetDb Lookups: Don't try to send a RI lookup to itself through a zero-hop tunnel 2010-01-15 15:16:58 +00:00
0a1960461a Fully clean up I2PTunnel. No more lint issues, should compile 100% clean.
Dropped unused class BufferLogger from I2PTunnel as it is not used anylonger.
2010-01-15 03:32:35 +00:00
11249657ac Clean up reverse connection ability, remove some annoyingly redundent code.
Place all settings in the console. It works!
2010-01-14 05:45:01 +00:00
zzz
188ac4f730 SSLEepGet 2010-01-13 22:33:43 +00:00
865116b3f4 merge of '1f636df6ff10db350d6b020b2e06daf842fb23e1'
and '5e5df32501efc3a7548958249e5bd99acf8edd8f'
2010-01-13 14:38:01 +00:00
zzz
9f28c06e9e 0.7.9, and:
* I2CP: Clean up resources on 5-minute leaseset timeout at startup
    * Increase max floodfills to 9 (was 6)
    * Temporarily disable routerInfo floodfill verifies
    * Fix .fr eepsite index css
    * Javdoc tweaks
2010-01-12 18:48:47 +00:00
zzz
3cd6520758 logging and javadoc tweaks 2010-01-10 22:01:00 +00:00
zzz
da1a50bfeb * VersionComparator: Move from TrustedUpdate.java to util 2010-01-10 16:42:21 +00:00
zzz
9ec79f50fa * I2CP: Clean up resources on 5-minute leaseset timeout at startup 2010-01-10 16:38:34 +00:00
b15392ea85 Insert reverse connection ability into the http server code so that
seedless can start to get worked on. It's disabled by default.
2010-01-10 11:23:20 +00:00
zzz
b8339e72b0 tweaks; include new translated eepsite pages in pkg; -18-rc 2010-01-09 14:26:01 +00:00
6eaec7fd44 Russian translation update 2010-01-09 03:01:04 +00:00
9e8f2ce771 Russian translation: Router console (969/969), router help page, eepsite help page 2010-01-09 02:58:49 +00:00
e8e6f6f531 Tagged missing strings. 2010-01-08 15:57:48 +00:00
f16ba8ee06 Tagged missing strings. Retagged (merged) couple strings to have 1 string per sentence instead of translating them chunk by chunk while their internal punctuation marks were outside of the translation scope. 2010-01-08 15:46:22 +00:00
zzz
76f11859b2 hide add button when editing 2010-01-06 21:33:53 +00:00
zzz
5be21a19db support add, delete,edit of clients 2010-01-06 21:24:08 +00:00
zzz
043359dd40 propagate from branch 'i2p.i2p' (head dbcd208a02bbecfe924e13a7d71297ece3f01ef3)
to branch 'i2p.i2p.zzz.test' (head 9eee20312852c80ca6c8e079174578a335edbe6d)
2010-01-06 17:16:18 +00:00
zzz
1b95b00b44 prevent more than one zero-hop tunnel in a leaseset 2010-01-06 17:16:00 +00:00
zzz
eaaf6af31d javadoc and logging tweaks; bring back i2ptunnel link to summary bar 2010-01-06 14:52:53 +00:00
d8d50aaf41 Snark font color fix 2010-01-03 14:12:48 +00:00
5fcddd581e Fix one last stupid mistake in build.xml, my fault. 2010-01-02 22:58:50 +00:00
f1a9613a92 merge of '4259744a4e2a56c50c62c34ecc3340120b48a427'
and 'd548b2a3c95f98dd3296cdd891e03e7c2936e61e'
2010-01-02 16:55:58 +00:00
a2ce10759c po update 2010-01-02 16:55:15 +00:00
5065aec773 Fix NB 6.8 goofyness... 'till ant 1.7.1 or > is needed, stay with NB 6.5,
as the newer ones place a check for 1.7.1. We require 1.7.0
2010-01-02 14:59:50 +00:00
25fc64933a Fix build.xml target for justBOB and fix Main build.xml so that it actually
deletes backup files and add a few extra types that should be commonly 
needed... atleast by me.
2010-01-02 14:34:20 +00:00
bbdd54efc8 Russian translation: Error pages (9/9) 2010-01-02 07:57:03 +00:00
92597baab9 Russian translation updated: I2PTunnel (138/138) 2010-01-02 07:56:35 +00:00
62786dcc09 Tagged couple of messages required for error pages (previously marked as fixme's) 2010-01-02 07:49:42 +00:00
c012e5bf17 tagging and translation 2010-01-02 05:43:50 +00:00
zzz
5ed29b6c27 laptop mode 2010-01-02 02:46:23 +00:00
zzz
2d5decd943 save refresh setting 2010-01-02 02:43:18 +00:00
zzz
9d167dc83a path fix 2010-01-02 02:40:58 +00:00
zzz
afe8394658 optimize URL encoder 2010-01-02 02:40:12 +00:00
zzz
72db6d1a08 alignment fix 2010-01-02 02:39:24 +00:00
zzz
9d0e300924 css update for readability 2010-01-02 02:38:35 +00:00
4f548b7b27 Added a target to generate a stand-alone BOB jar file. 2010-01-01 21:28:28 +00:00
cbd50372e4 Fixed: braceless if (where it proved to be harmful) 2010-01-01 17:33:55 +00:00
zzz
3caee8bc71 i2ptunnel java tagging and fixups 2010-01-01 14:58:21 +00:00
6c64faf0ba translation 2010-01-01 14:31:06 +00:00
65290f1ed7 Russian translation update/reworded 2009-12-31 21:00:17 +00:00
498af5d203 i2ptunnel\jsp tagging and translation 2009-12-31 13:10:33 +00:00
zzz
883b53de0a cleanups, javadoc 2009-12-30 22:38:37 +00:00
zzz
cefc1f130d * NetDb: Fix exploration by adding a null hash to mean
"don't give me floodfills"
    * PeerSelector: Downgrade floodfills with high fail rate
2009-12-30 22:36:53 +00:00
zzz
b2a137c5bc make BuildResponseRecord static 2009-12-30 22:33:26 +00:00
zzz
62f056f884 remove more unused logs 2009-12-30 22:28:07 +00:00
zzz
3944ea53d2 make the message box big enough that we dont need a scrollbar 2009-12-30 22:26:36 +00:00
zzz
d372ea753f fallback to external socket 2009-12-30 22:26:02 +00:00
zzz
2528cd205d javadoc 2009-12-30 22:25:34 +00:00
zzz
afd54fc212 logs.jsp tweak 2009-12-30 22:25:21 +00:00
8e7a9fc513 update translation 2009-12-27 05:43:25 +00:00
zzz
acb75f4212 oops 2009-12-26 20:37:05 +00:00
zzz
c40b56c19d -12 2009-12-26 20:28:11 +00:00
zzz
98027a06ec javadoc 2009-12-26 20:26:47 +00:00
zzz
d92dfec1bf * UDP: Bid lower than NTCP when we need introducers and don't
have enough; was preventing firewalled routers from
      being reachable
2009-12-26 20:25:32 +00:00
zzz
72a588bfbf * Tunnels
- More code to detect improper reuse of cached objects
        after release
      - Don't pass a msg with a failed IV on to
        the FragmentHandler at the OBEP
      - More cleanups and comments
2009-12-26 20:20:11 +00:00
zzz
213bc4bb71 - Prevent release of TunnelDataMessage cached ByteArray,
as it may be reused if retried in another transport;
        a nasty bug causing corrupt messages
      - Lots of code to detect improper reuse of cached objects
        after release
2009-12-26 20:12:43 +00:00
zzz
1a01aa0ae4 - Code to detect improper reuse of cached objects
after release
      - Prevent race with released resources in UDP OutboundMessageState;
        a nasty bug causing corrupt messages
      - More cleanups and comments
2009-12-26 20:05:41 +00:00
zzz
0b0e3fffe4 various cleanups, javadocs, logging 2009-12-26 20:00:47 +00:00
zzz
1fc32c5e6f more logs.jsp tagging 2009-12-26 19:54:27 +00:00
ba9f05ca06 translation update 2009-12-26 09:55:16 +00:00
zzz
629d12ade1 * Tunnels:
- Do RED dropping before the IBGW fragmenter, not after
      - Change batch time to 250ms for IBGWs (was 100ms)
      - Change batch time to 150ms for exploratory OBGWs (was 100ms)
      - Start a new message in the fragmenter if almost full
      - Fix a major, longstanding synchronization bug in the FragmentHandler
        which led to corrupt messages at the endpoints
      - More cleanups and comments
2009-12-22 15:08:10 +00:00
zzz
08929752a6 move SubmitMessageHistoryJob to test 2009-12-22 15:02:28 +00:00
zzz
aaa5b4ca86 oops 2009-12-20 15:05:58 +00:00
zzz
8d7e84494b -10 2009-12-20 15:00:19 +00:00
zzz
99df95697a merge of '5cbdacfbeb8f09f9ac497016e429eaf6fe7225c6'
and 'dae5a2b76e24fc3215d46d5b96ea0f547c83f63c'
2009-12-20 14:52:57 +00:00
zzz
a877b21839 more comments and cleanup 2009-12-20 14:50:41 +00:00
3f267693d2 Russian translation update/reworded: I2PSnark, SusiDNS 2009-12-20 07:11:39 +00:00
zzz
30b7dbf1f7 Tunnel fragmenter cleanup, prep for enhancements 2009-12-19 22:20:58 +00:00
f32d162b62 Russian translation update: SusiDNS (83/83) 2009-12-19 18:23:18 +00:00
126fa320e5 susidns UTF-8 fixes for POST requests (yep, blame tagged 'action' parameters) 2009-12-19 18:16:28 +00:00
zzz
ecae0b055d schedule the outbound rather than sleep the thread for 3 seconds 2009-12-19 18:15:21 +00:00
zzz
9bf22fb0d3 stats.jsp tagging 2009-12-19 17:41:47 +00:00
zzz
2a1d358141 * Profile, DBHistory:
- Tweak the rate periods
      - Add a global fail rate stat
      - Increase the HashMap sizes
2009-12-19 17:10:39 +00:00
zzz
579b450029 clean up context usage 2009-12-19 16:56:38 +00:00
zzz
72eafe0920 * Tunnels: Reduce the drop probability for TunnelBuildMessages at the OBEP 2009-12-19 16:54:59 +00:00
zzz
f226392c9d static access fix 2009-12-19 16:53:49 +00:00
zzz
2cd5c209f5 unused cleanup 2009-12-19 16:52:49 +00:00
zzz
f0d444b32e add to javadoc and adjust logging 2009-12-19 16:52:18 +00:00
zzz
4baff9fbab * Router: Move some more threads to I2PAppThread so an OOM won't crash the router 2009-12-19 16:49:55 +00:00
zzz
8e656427d8 * Console:
- Fix status to show a disconnected network error rather than
        clock skew or UDP error when disconnected
      - Use peer clock skew rather than clock offset for determining
        whether to display clock skew error, i.e. display what matters
    * Transport: Rework peer clock skew method to always return a value
      by falling back to router clock offset;
      Fix possible AIOOBE and divide by zero; remove logging;
      reduce min number of peers
2009-12-19 16:47:18 +00:00
zzz
aaa7302e80 clarify table headings 2009-12-19 16:40:57 +00:00
zzz
33407fd5be reduce delays (cuts 10s from router startup 2009-12-19 16:39:50 +00:00
zzz
513b93f789 no room for cows 2009-12-19 16:39:06 +00:00
zzz
08e54c515e add isRouterContext() method 2009-12-19 16:37:44 +00:00
zzz
55682810b1 doc updates 2009-12-19 16:35:15 +00:00
ec893d09d0 as promised. translation done. Snark still needs review. 2009-12-18 08:27:17 +00:00
zzz
f9b745a671 * Log:
- Close old file on rotate
      - Buffer writes
      - Write in UTF-8
2009-12-18 00:04:16 +00:00
zzz
43b71a263c * Tunnel building:
- Increase timeout to 13s (was 10s)
      - Fix tunnel.buildReplyTooSlow stat
      - Tweak logging
      - Prioritize expl. builds over client builds
      - Code cleanups
2009-12-17 23:45:20 +00:00
zzz
5c4672d1e3 drop another unused class 2009-12-17 15:49:17 +00:00
zzz
7ca8e0c3a1 fix spacing in update section 2009-12-17 14:02:02 +00:00
zzz
b530316850 * I2CP:
- Move client-side writes to their own thread
      - Reenable InternalSockets
2009-12-17 01:05:29 +00:00
zzz
fa92beae5a more cleanup and tagging; remove untranslatable button images; add button css 2009-12-16 17:29:28 +00:00
zzz
f58f703ecb add some newlines to the source 2009-12-16 17:26:49 +00:00
zzz
6b83fc6b3b InNetMessagePool cleanup 2009-12-16 17:25:09 +00:00
zzz
cdb390f7ce fix bundle script 2009-12-16 17:23:52 +00:00
zzz
7b1caac9ac cleanup and tag susidns jsps 2009-12-15 17:25:01 +00:00
zzz
cec75fa60e fix i2ptunnel bundles 2009-12-15 01:51:56 +00:00
zzz
eb23306b12 configurable jump list 2009-12-15 01:48:57 +00:00
zzz
43f6813609 snark start/stop fix, action cleanups 2009-12-15 01:47:24 +00:00
zzz
ea36b7b153 susidns UTF-8 fixes 2009-12-15 01:46:10 +00:00
zzz
448ff4d398 better error msg on sud copy fail 2009-12-15 01:45:15 +00:00
zzz
e16227211f remove unused logs 2009-12-15 01:44:20 +00:00
zzz
e07e329c26 Tunnels: static fix, synchronization fix, deprecate setPairedTunnel() 2009-12-15 01:41:43 +00:00
a3d79aaa4e Russian translation: I2PSnark (140/140), SusiDNS (1/1), I2PTunnel (3/3) 2009-12-14 20:15:16 +00:00
zzz
3fa9ae0b82 * Find ResourceBundles in wars
* Fix restart from config.jsp if no wrapper
    * i2psnark: Elaborate popups
2009-12-13 15:47:51 +00:00
dev
7feed50af4 -5 2009-12-13 09:26:10 +00:00
dev
0c0eb5765d merge of '306029c0c1bb9b7d62fcfdaeddd47bff7db82f66'
and 'c14952061dd61ddd6638f0a3655dd818f0a3db8e'
2009-12-13 09:25:09 +00:00
dev
e87ff25ef6 fix NPE 2009-12-13 09:24:25 +00:00
21e09cb0a5 no more 8887 2009-12-13 07:35:30 +00:00
04d54607ae merge of '63c4c4c5586988695f01b6e845851bad2196b89a'
and 'db28ef1a2085d0585cc3606f1e614467913f758b'
2009-12-13 06:39:08 +00:00
ad8bfbdaab merge of 'afee8fe3ed03c61266ad369b5ce5408382948977'
and 'cec49ea3b0b9120ba6e58435852fb18c06912c55'
2009-12-13 06:39:05 +00:00
aca815c4aa snark rough translation (i am not a bt guy, so need review and refine) 2009-12-13 06:38:39 +00:00
24683c19a4 Added messages_ru.po with 100% fuzzy translations. Awaiting review by native. 2009-12-12 18:18:46 +00:00
dev
6b8dffc401 -4 2009-12-12 17:51:01 +00:00
dev
c4bb84058a sort peers per country 2009-12-12 17:49:54 +00:00
zzz
c3dc76e35f disable internal sockets until I can fix the borkenness 2009-12-12 01:36:57 +00:00
zzz
993fa5c210 fix all summary bar relative links 2009-12-11 19:03:30 +00:00
zzz
1cec793217 add missing file, prop history, -2 2009-12-11 18:26:53 +00:00
zzz
6029e1a291 * Fragmenter: Pull the new comments, new stats, and
debug log fix from i2p.i2p.zzz.batch in - but not the
      batching mods, which need a fresh look.
2009-12-11 18:00:34 +00:00
zzz
7cc75c0cb9 html fix 2009-12-11 00:42:25 +00:00
zzz
e5248b09ab add 2-param method, tag the java messages, fix the buttons, clean up add and create forms 2009-12-10 18:08:50 +00:00
zzz
c39f047703 pretty much the last of the tags 2009-12-10 14:52:09 +00:00
zzz
4562254862 propagate from branch 'i2p.i2p' (head f672021bb9871a728005be3bd9581710738b9e5f)
to branch 'i2p.i2p.zzz.test' (head e115e218dbb666839e69fa1e1ba7378554b9874f)
2009-12-10 13:34:05 +00:00
zzz
8116d88aaf translation build fixups 2009-12-10 02:12:18 +00:00
zzz
14362630d7 translation support 2009-12-10 01:54:49 +00:00
zzz
9af796a10a translation support 2009-12-10 01:06:55 +00:00
zzz
eeb884e8ce more tags 2009-12-09 23:36:18 +00:00
zzz
02baf905c6 more tagging 2009-12-09 21:22:06 +00:00
zzz
df7029d2c2 translation support and initial tagging 2009-12-09 20:54:10 +00:00
zzz
c22b7568b1 * Translation: Move code from routerconsole to core,
to support translation of other webapps
2009-12-09 14:07:16 +00:00
73537d27d0 bump as requested 2009-12-08 15:27:14 +00:00
449d7ab589 typo 2009-12-08 14:53:25 +00:00
zzz
0ddef91e16 more last-minute tweaks 2009-12-08 13:33:42 +00:00
zzz
b205af5a0d 0.7.8 2009-12-08 12:22:56 +00:00
zzz
1e32170df2 move hosts.txt; do distclean in apps/jetty 2009-12-08 01:20:13 +00:00
zzz
f446a5f1fc * Misc. cleanups after review, prep for release 2009-12-08 00:41:58 +00:00
zzz
fb21fb25ee * I2PTunnel:
- Switch all I2PThreads to I2PAppThreads
      - Run an InternalSocket as well for the HTTP Proxy
    * EepGet: Use InternalSocket
    * Console: Change "depth" to "length"
2009-12-07 21:25:27 +00:00
zzz
deae0e8856 truncate the history in the updater 2009-12-07 21:24:03 +00:00
zzz
1cd54dc12e * netdb.jsp: Fix bug caused by XSS fix
* Translations: drop ru until after release
2009-12-06 21:42:28 +00:00
zzz
8ebc8bd209 merge of '07a757695fb1dc6eb2cfda52c8fc38aee4e61f53'
and 'a85053bedf64d2793ad1f55f396390baf09edcc1'
2009-12-06 21:35:02 +00:00
9d11866f86 Removed Russian .po file. A native Russian speaker is working
on a translation of the router console for the next version 
of I2P. Update the readme files to include a Russian flag.
2009-12-06 21:15:12 +00:00
zzz
2c456c291a remove jsps from war 2009-12-06 17:44:53 +00:00
zzz
c5b3c2f430 add restart msg as requested by dr|z3d 2009-12-06 15:17:47 +00:00
zzz
e46e747ac0 add the anchor 2009-12-06 15:16:52 +00:00
zzz
e1a88c9426 drop 6 unused classes 2009-12-06 15:07:03 +00:00
23d3c33a12 Update to german console translation 2009-12-06 11:49:43 +00:00
ec8130f443 Improved readme_ru.html translation.
All strings in messages_ru.po translated roughly.
A few words in messages_ru.po edited for excessive length.
2009-12-06 03:54:21 +00:00
4b7aeb8418 update to german translation, need more work 2009-12-05 23:21:29 +00:00
18a0f01f8b corrected typo 2009-12-05 22:15:05 +00:00
df2e639692 first rough translation into german 2009-12-05 20:41:20 +00:00
zzz
708b3a662c * Build: Fix poupdate dependency
* Console: Add Russian option
2009-12-05 17:19:23 +00:00
zzz
4fee7844f8 merge of 'd34b6676e413f6e88f9e145f8ddde79a66ce6bb1'
and 'da507e67b02527a43e8cca4b5b20c2de18a3142c'
2009-12-05 17:06:34 +00:00
891416e6b9 Added Russian localization files 2009-12-05 16:47:02 +00:00
978cd2c484 * BOB: fix a critical bug causing ghosts on probes and remove unused code. 2009-12-05 13:26:40 +00:00
c88c905926 rev 2009-12-04 21:27:59 +00:00
zzz
bda4eb830e prevent accept() hang on internal socket 2009-12-04 11:16:43 +00:00
zzz
f5c1acc749 Fix potential XSS holes 2009-12-04 00:27:05 +00:00
zzz
c4e6148b9f config cleanup, more HTML transitional fixes 2009-12-04 00:22:46 +00:00
zzz
43029de2f3 point to translated pages on www.i2p2.i2p 2009-12-04 00:22:12 +00:00
zzz
7262c014c0 * I2CP: Implement an internal "socket" class that
allows clients in the same JVM to connect to the
      router without going through the kernel
2009-12-04 00:20:43 +00:00
zzz
9f7bd99051 fix popup based on torrent type 2009-12-02 16:50:42 +00:00
zzz
9e4f04cc18 fix exception text 2009-12-02 16:50:15 +00:00
454b2c8941 An updated (yet incomplete) version of messages_fr.po 2009-11-30 20:46:23 +00:00
zzz
4c812c7bff * HTTP Proxy: Don't send proxy.i2p to the naming service,
it was making the error pages load slowly
2009-11-29 18:49:28 +00:00
zzz
f95b5324e0 profiles.jsp: Hide non-ff from ff table 2009-11-29 18:48:03 +00:00
zzz
64ee1b313b Comment out unused stuff better 2009-11-29 18:47:34 +00:00
zzz
1ca651e803 Fix an error message 2009-11-29 18:47:12 +00:00
zzz
f3a88398f2 Fix the default inbound burst 2009-11-29 18:46:48 +00:00
zzz
412d641eb6 fix pathspec 2009-11-29 18:40:20 +00:00
zzz
d7d058e772 addressbook servlet cleanup 2009-11-29 17:58:24 +00:00
278b917494 net.i2p.router.transport.udp deadwood code cleanup.
documented rare NPE in InboundEstablishState.java.
2009-11-29 15:02:50 +00:00
zzz
4b6989ef7b * Addressbook, susidns: Rework addressbook into a
HttpServlet, so susidns can kick it when the subscription
      list changes
2009-11-28 17:08:02 +00:00
zzz
c10ea84ade * NamingServices
- Move default reverseLookup to base class
      - Deprecate unused services
2009-11-28 14:37:07 +00:00
0642fa8093 * Improvement to BOB's TCPio to hopefully lower load average. It seems
to be helping a little when stress-tested with Robert.
2009-11-28 13:53:34 +00:00
zzz
2db7c2bdd8 new 2009-11-28 13:38:35 +00:00
zzz
8682e7deb5 cache the hash of the Hash 2009-11-27 16:29:15 +00:00
zzz
ea0747171f * NetDb:
- Switch from ArrayList to ConcurrentHashSet in
        KBucketImpl to reduce chance of deadlock;
        remove periodic shuffling of the bucket,
        needs to be addressed elsewhere
2009-11-27 14:39:53 +00:00
zzz
13349777ad propagate from branch 'i2p.i2p' (head f42d02067d4fb58b86ffb79222a285f26c3a2628)
to branch 'i2p.i2p.zzz.test' (head 2ceb319557032e54cc8ace070515c6d540e0a7a4)
2009-11-27 13:26:52 +00:00
zzz
ab0a5a06af add basic no-webapp handler 2009-11-27 13:26:38 +00:00
z3d
6371f66677 Midnight console theme tweaks. 2009-11-27 12:03:56 +00:00
zzz
105524d9c0 remove another 8887 reference 2009-11-24 20:22:31 +00:00
zzz
95e0492b32 * Profiles: Record successes in the DB fail rate
too, so we can calculate a percentage
    * profiles.jsp:
      - Change fail rate from count to percent
      - Hide standard profiles by default
2009-11-24 20:20:30 +00:00
zzz
234c084c2a * OrderedProperties: Vastly implify, use in i2psnark 2009-11-24 20:15:29 +00:00
zzz
94faf74aa4 * Streaming:
- When an "immediate" ack is requested, do it within
        250 ms (was 2000)
      - Request immediate acks when < 1/3 of window remains,
        or when < 3 packets remain in window,
        and every 8 packets (was when < 2 packets in window remain)
      - Change requested delay to RTT/2 (was RTO/2)
      - Log cleanup and javadoc
2009-11-24 20:12:27 +00:00
zzz
e78dd1fdc3 remove unused Logs from DataStructures 2009-11-24 20:08:58 +00:00
zzz
38045d876d fix paths so poedit source viewer works 2009-11-22 13:07:34 +00:00
zzz
8433724452 * Netdb Floodfill rework part 4 of N: Search closest-to-the-key 2009-11-21 13:50:39 +00:00
zzz
e9f9e0dabb - Adjust response time limit 2009-11-21 13:47:51 +00:00
zzz
6bdf750c19 javadoc 2009-11-21 13:45:40 +00:00
zzz
647a09b5b9 - Put closest-to-the-key in explore don't-include-list
- Use facade's peer selector for exploration rather than
        instantiating a new one
2009-11-21 13:41:48 +00:00
zzz
6144bfb437 Comment out test code 2009-11-21 13:35:52 +00:00
zzz
88dbd7710a * Routerconsole build: rename include files so they aren't
compiled and bundled separately (~15KB)
2009-11-21 13:33:57 +00:00
zzz
26a71232f0 add popups on flags 2009-11-21 13:32:32 +00:00
zzz
f58a1768b9 Nov 17 09 geoip 2009-11-21 02:14:58 +00:00
dev
125e6581e0 moved the file to the i2p.scripts branch 2009-11-20 22:30:03 +00:00
54105086ad pass the first following parameter as PARAS
add messages_{langcode}.only support to only update for a specified language
2009-11-18 16:45:42 +00:00
3674ac2922 rev 2009-11-18 15:08:16 +00:00
18c023e6f7 merge of '6c2ef00502207c28f02c90cef00b19d75f09d9a4'
and 'de35fdcdc8943537c71571c5c9d8320a24768cdf'
2009-11-18 15:05:14 +00:00
zzz
312ba2599f - Note failed floods in the profile
- Reduce max flood
2009-11-18 14:24:38 +00:00
zzz
746dc6f884 - Adjust criteria for following DSRM 2009-11-18 14:20:43 +00:00
zzz
edd4d4c114 - Floodfill rework part 3 of N: Send closest-to-the-key in DSRM replies 2009-11-18 14:18:16 +00:00
zzz
56e0c3e047 * Build: Don't update the po files by default, add new
target "poupdate" to do that.
2009-11-18 14:16:36 +00:00
1e83d1b304 small revision 2009-11-18 10:01:20 +00:00
z3d
74aa84b183 merge of '369305db0cea95e8bd0990de7462340cac75a1f9'
and 'f58179e91c798b6d06faf4fbcf2ee6bf106475de'
2009-11-17 19:59:43 +00:00
z3d
168c213288 Some string mods and tagging and so forth; "midnight" console theme futzage. 2009-11-17 19:55:51 +00:00
d268a3852c A first incomplete French version of the router console translation file messages_fr.po 2009-11-16 21:36:46 +00:00
dev
01e87438c3 merge of '18a7dd067a56c2552cf30f4a045628f91c360c80'
and 'd6b8e99c4aee82652446fe759f45f27e0da9fbc0'
2009-11-16 19:45:10 +00:00
dev
060f4e6632 disapproval of revision 'd07b92fb678f4dc87b62eaaeab002820b25583b6' 2009-11-16 19:44:54 +00:00
z3d
3df5540a97 Tweaks to client.config tunnel descriptors; more "midnight" theme adjustments. 2009-11-16 19:15:15 +00:00
z3d
30dec5b9f5 merge of '3d1905aaefa398767d0df1945eaaf6d923767405'
and 'd07b92fb678f4dc87b62eaaeab002820b25583b6'
2009-11-16 11:30:19 +00:00
43b437fc58 Initial checkin of apps/i2pbote/** 2009-11-16 07:28:14 +00:00
zzz
8e889cd292 bye TPB 2009-11-15 23:50:45 +00:00
zzz
eceac6def0 Shitlist: Fix bug from two checkins ago, all were forever 2009-11-15 23:47:01 +00:00
zzz
1e3d6776aa Take two test scripts out of the installer 2009-11-15 23:45:39 +00:00
zzz
784ca67ddf Move class to net.i2p.addressbook 2009-11-15 23:44:20 +00:00
0f6b49cc31 A new French version of eepsite_index.html 2009-11-15 12:25:03 +00:00
8cede2a2b2 term: Adresses => Transports 2009-11-15 11:00:14 +00:00
38ed04bbd8 trans 2009-11-15 06:02:07 +00:00
zzz
c393e70ca9 * HTTP Proxy:
- Add support for error page translations
      - Add support for external pages for all errors
      - Fix lack of \r in error page headers
      - HTML transitional fixes
      - Cleanups
2009-11-14 15:05:44 +00:00
zzz
1c25c0f408 * UDP PeerTestManager: Throw in some synchronization to try to fix stuck tests 2009-11-14 15:00:28 +00:00
b7ebce48ee the only tool that once successfully resume a download from an eepproxy ;-) 2009-11-13 05:41:14 +00:00
d6814a0489 merge of '177b5d58442cfa7d68c6a9adce7f40e681c6cd41'
and 'd1762684a780fa61d199e583bd9442b1e2a2af6e'
2009-11-13 05:28:51 +00:00
z3d
6f24c74f8c More "midnight" theme finessing. 2009-11-12 19:07:05 +00:00
d8389dcc46 stop duplicating, use "source bundle-messages.sh" 2009-11-12 14:07:15 +00:00
9f939553ee rev 2009-11-12 14:04:40 +00:00
z3d
529988f394 merge of '1dad9833f19c3370d3f1db58bc580c5b8c21c961'
and 'aaedb6e8d35bd3cca935c418a7fdcd2895bf2067'
2009-11-12 13:25:08 +00:00
z3d
9f46aa1e18 Fixes and tweaks for "midnight" console theme. 2009-11-12 11:04:28 +00:00
418c1b6f96 shared tunnels for _(name) 2009-11-12 03:17:33 +00:00
8056fb9502 rev 2009-11-12 03:14:31 +00:00
z3d
ab2e21147f Tweaks to "midnight" console theme. 2009-11-12 00:01:57 +00:00
zzz
6c00bb20b6 * Console: Some colon cleansing
* Shitlist: Move HTML renderer to router console,
      add cause parameter for ease of translation,
      tag all causes
2009-11-11 20:28:13 +00:00
zzz
573ac357d8 ff ranking tweaks so they arent all bad 2009-11-11 20:24:59 +00:00
5b139f9246 more translation and possiblely all has been done. 2009-11-11 15:56:57 +00:00
z3d
76d75b712e Updates to "midnight" console theme. 2009-11-11 09:03:19 +00:00
zzz
8bc2fd7e42 3rd time... 2009-11-10 21:27:01 +00:00
zzz
4533a86712 -15 2009-11-10 20:39:09 +00:00
zzz
a6239e2ce3 merge of '2232dc91d5c2e9f60934f66bc11519f49399cc5b'
and 'a831cd0f05f3dcf5d877ff68b14fef2497cde44a'
2009-11-10 20:14:16 +00:00
zzz
1f8e61f480 verify using closest-to-the-key 2009-11-10 20:11:08 +00:00
zzz
c40f845279 fix good/bad calculation 2009-11-10 19:02:59 +00:00
zzz
aa74962263 * DataHelper: Fix broken byte[] compareTo() used by XORComparator,
was not doing unsigned comparisons!
    * Floodfill rework part 2 of N:
      Store closest to the key, subject to last failed
      lookup and store stats.
    * FloodfillPeerSelector: Use standard XORComparator
      instead of messing with BigInteger
    * FloodfillVerifyStoreJob: Set correct timeout for
      requeued store job
    * KNDF: Rework getPeerTimout() to use 1 day averages,
      and lower the min, max, and multiplication factor.
    * Publish jobs: Lengthen timeout to 90s (was 30s for
      routerinfos and 60s for leasesets)
    * StoreJob: Limit max peer timeout to 15s for direct stores
2009-11-10 18:24:15 +00:00
zzz
42cbd6c12b console tweaks 2009-11-10 14:45:53 +00:00
zzz
ee51f69a5a * Addressbook, NamingService: Allow 516 byte dests
that end with AA but not AAAA, so we can permit
      non-null zero-length certs.
2009-11-10 14:44:40 +00:00
z3d
0fb6e9cf6c Minor tweaks to console_big.css in classic & midnight following feedback from "walking". 2009-11-10 14:16:54 +00:00
zzz
e02845076d * Netdb StoreJob, FloodfillVerifyStoreJob:
- Fix bug where reply selector wasn't registered for
        routerinfo stores, so we didn't get stats, and
        we kept retrying. This also prevented verification
        and profile updates for routerinfo stores.
        This bug was introduced 4 years ago by the change to
        store routerinfos directly.
      - Add dbStoreSuccessful() to profile, and have FVSJ
        call it or dbStoreFailed() as appropriate to give
        credit or blame to the floodfill we stored to.
      - Don't let FVSJ verify using the peer we stored to
2009-11-10 01:24:39 +00:00
zzz
2dc3798116 drop 2 extra lines only in the iframe 2009-11-10 01:23:14 +00:00
z3d
fa252f5e8f Retrofit "dr|z3d" to history.txt for latest updates. 2009-11-09 18:28:01 +00:00
z3d
580b9b450f Add "midnight" theme to the installer manifest; bump to -14. 2009-11-09 18:00:08 +00:00
z3d
f0730cd1c8 Introducing a new console theme, "midnight". Lightweight midnight blue theme, IE compatible. 2009-11-09 17:49:17 +00:00
zzz
b045fb3a45 * FloodOnlySearchJob:
- Fix up field hiding and duplicate overrides
      - Other javadoc and java 5 improvements
2009-11-09 17:23:22 +00:00
z3d
6c64111d7e Further tweaks to console_big.css for the classic theme. 2009-11-09 17:21:24 +00:00
zzz
37a2ccca95 * Streaming: Fix unused resend delay field in the packet header,
it is defined as seconds and we were not dividing by 1000,
      so we were truncating 1000 to one byte which equals 232.
2009-11-09 17:21:17 +00:00
zzz
b4615edfcc * UDP:
- Better handle a test reply from bob with a 0-length IP
      - Add config options for min and max random port
2009-11-09 17:16:51 +00:00
zzz
6019cf8148 * Console:
- Tag tunnel status
2009-11-09 17:15:19 +00:00
zzz
e3d945201b - Add transport table to netdb.jsp 2009-11-09 17:11:20 +00:00
zzz
05b17e5a00 * i2psnark:
- Reject torrents with too many pieces
      - Reject torrents with a single file named *.torrent
      - Increase max piece size to 2MB (was 1MB), but reduce
        max number of connections to lessen ooms
2009-11-09 17:09:53 +00:00
z3d
13b3edfb07 merge of '8c614ff109c2cc345b90363355950ab46989dab8'
and 'e635717562ad75828dfc6ca42abf1f5593d71ba0'
2009-11-09 04:07:51 +00:00
z3d
f61372b2fd Streamlined & tweaked console_big.css for our Chinese friend(s). 2009-11-09 04:07:05 +00:00
f85d8f7060 tag a link in confstathandler
update zh.po
2009-11-08 13:15:48 +00:00
zzz
a0b4b7db86 * Console:
- countries.txt: Convert to mixed case, include in update
      - netdb.jsp: Hide all routers by default, sort and tag country names
      - oldstats.jsp: Move to stats.jsp
      - profiles.jsp: Show new DBH times instead of counts
    * Profiles:
      - Track last good and bad lookup times
        and last good and bad store times,
        to prep for floodfill changes
      - Don't reset last-heard-about at router startup
    * Checklist and Android readme fixups
2009-11-07 19:32:00 +00:00
827a92ef2f bundle-messag windows hack 2009-11-05 13:35:33 +00:00
625d76b914 + --from-code=UTF-8 2009-11-05 02:12:02 +00:00
a1de894b64 zh.po regenerate/rev 2009-11-05 01:06:52 +00:00
zzz
413ab6d7e4 -12 2009-11-04 16:12:59 +00:00
zzz
a3b1c79006 merge of '0d58ec9e2b160029e92a584b0c707ffdf4f25c7e'
and 'd4e270a4df0c8134d7bac1585e30ef8ddef37f85'
2009-11-04 16:06:46 +00:00
zzz
5a7d3ba4c8 move things to installer/resources; fix initial news 2009-11-04 15:36:13 +00:00
zzz
8a1db31184 reduce max msg delay 2009-11-04 12:54:02 +00:00
5190b2db1f Fixups to Slackware scripts 2009-11-04 10:27:02 +00:00
zzz
820c573476 tags 2009-11-03 20:37:21 +00:00
zzz
ab40454bce reduce the routerinfo expiration a little 2009-11-03 17:38:11 +00:00
b65865b854 tagged "Redraw"
two translation revision
2009-11-03 15:17:14 +00:00
zzz
a5772e62c3 flags 2009-11-02 18:52:42 +00:00
zzz
9976bea03f * Profiles:
- Remove the almost-unused send and receive size RateStats;
        this also reduces the effective time for isActive()
      - Only store DB history on-demand to save space;
        fix up resulting NPEs
2009-11-02 16:50:28 +00:00
zzz
7997aeaca5 adjust the help due to random port 2009-11-02 16:46:07 +00:00
zzz
ba95084d27 bold the transport 2009-11-02 16:45:23 +00:00
zzz
e952e91b54 tagging 2009-11-02 16:45:04 +00:00
zzz
da21c0ddb7 * UDP: Pick a random port on first install or bind failure -
No more port 8887 to prevent easy state-level blocking
2009-11-02 16:43:04 +00:00
zzz
0133711c3b code cleanup 2009-11-02 16:41:01 +00:00
z3d
6eae2cd460 Console_big.css tweaks. 2009-11-01 23:54:55 +00:00
9314eebc4f trans rev 2009-11-01 03:51:07 +00:00
zzz
428cbdce2a * Console:
- More tagging
      - Show user-installed themes on configui.jsp
      - Fix reseed button spacing
    * GraphHelper cleanup
    * Susidns: add link to subscription faq
2009-10-31 18:18:36 +00:00
7594c4383b tagged one more string 2009-10-31 17:01:46 +00:00
e2f6911e9f closed an open <a> tag 2009-10-31 04:09:25 +00:00
zzz
9cdae03069 evict another test class 2009-10-30 17:52:58 +00:00
06946f026e merge of '6416a3499b7666362959e13c5996a3c925a80b60'
and 'd36896148eb8067f68c653029fe60c09564a2bd8'
2009-10-30 14:05:45 +00:00
d43dac5c04 more tagging and trans
term rev [not failing] -> [Standard]
1 string(notice) with link still left in confstats
2009-10-30 14:04:58 +00:00
zzz
b4d83b18fa tag and script fixups 2009-10-29 23:22:51 +00:00
f9424dbd6d tag and trans
convert append(""+""+"") to append().append().append()
2009-10-29 09:03:32 +00:00
zzz
e5212937af * Console:
- Remove limiter status from peers.jsp
      - Fix UPnP status header
2009-10-28 22:12:10 +00:00
zzz
aeb6635e71 * Console:
- Rewrite TrustedUpdate version comparator, use for netdb version table
        so 0.7.10 will be sorted correctly
      - Reduce netdb.jsp memory usage
      - More tagging fixups
      - configclients.jsp fixup for "Web console"
2009-10-28 18:26:50 +00:00
zzz
e94b478317 * NetDb:
- Generate new RI immediately at startup
      - Try again to not publish RI until we have been up a few minutes
2009-10-28 18:18:21 +00:00
88216de42c revise pos. and button names in readme 2009-10-28 16:12:17 +00:00
1fcf707bb2 revise v1 2009-10-28 03:41:41 +00:00
z3d
5101486fe7 Tweak to classic theme, somewhere. 2009-10-27 19:39:45 +00:00
z3d
7ae4d0e981 merge of '54ec7a68eb12d95085a669bc5320e332f98f95b9'
and 'c145f6f7910b49e65fbbd9ab94a06893d620dbba'
2009-10-27 18:30:31 +00:00
z3d
c644c128c0 merge of '41f3b25fb9d92bf586913d80bc8174fd07567236'
and 'aaac66c060e4f5e3892662cb387e4f0bc6b67ce8'
2009-10-27 16:05:00 +00:00
2603f6fe45 summarybar tagging 2009-10-27 13:35:27 +00:00
z3d
957a296ca9 Correct the misalignment of the local destinations list in dark theme. 2009-10-27 12:38:51 +00:00
z3d
e4f44fa1e9 Classic theme override for Chinese and other "big" charactersets (sidepanel). 2009-10-27 12:31:24 +00:00
2b469567bb more tag and more translate 2009-10-27 11:11:51 +00:00
zzz
a2d90eebea * Console:
- Don't save config when checking for updates on configupdate.jsp
      - Rework ConfigRestartBean and tag
      - More tag fixups
      - Add lang=xx for testing
      - Add file for additional tagged strings
2009-10-26 21:48:46 +00:00
zzz
850a8da0a9 propagate from branch 'i2p.i2p.zzz.test' (head 16046dc1b2fd2a8b10de465cf238233f5d6954af)
to branch 'i2p.i2p' (head f222777c65da9e465bbf717582b4384d31848e07)
2009-10-26 15:20:30 +00:00
zzz
ac6d711a99 * Console:
- Add parameterized tag
      - Refactor confignav.jsp to java and tag
      - Start tagging profiles.jsp
2009-10-26 14:24:25 +00:00
zzz
5aa254a178 add comments 2009-10-26 14:18:57 +00:00
ad396adf39 merge of 'a45e1691786f0464f669fdeaa493cf76601879e4'
and 'bc220af9e0a1d5d674d89c215300b311a77e6ab6'
2009-10-26 11:01:58 +00:00
05cce164f7 all tagged all java except :
- summerbar related files since drz is working on it
- string requiring word reordering
- string with link in the middle
- string which looks unusual
- string found not in router console source
update the POs
2009-10-26 10:53:53 +00:00
935b69bc71 Tagged buttons and message on conf- Net,Service,Update,Client
update Translation
2009-10-26 02:21:15 +00:00
dev
61f800999a some more updates to the code_swarm script 2009-10-25 15:52:23 +00:00
dev
9833743eb9 clean up codeswarm script 2009-10-24 16:00:37 +00:00
dev
ac65bc7302 merge of '42bb0b558f03e9a0de9116377c2e229d57da8ef3'
and 'e14fbe535deef3e6b734ad65bfb4ea32b58b85fe'
2009-10-24 15:59:24 +00:00
dev
b36f207bb2 small utility script for codeswarm 2009-10-24 15:59:15 +00:00
e87a7c7bb4 add classic\console_big.css for reference only :)
add tag several missing strings in config.jsp
update the POs.
2009-10-24 12:46:01 +00:00
7e5128bb85 ConfigServices.jsp fix, update the POs 2009-10-24 08:48:06 +00:00
0a178ec35e keep tagging tagging tagging t.. plus updated pos 2009-10-24 06:10:40 +00:00
zzz
a5cd0bdd3f - Rename cssHelper to intl for ease of tagging
- configui.jsp post-prop fixup
2009-10-23 13:55:44 +00:00
zzz
9cbf9d0422 propagate from branch 'i2p.i2p.zzz.test' (head 2baf6dba31abb4ce4b51c8eba75b9338ee7c4998)
to branch 'i2p.i2p' (head ef05271bc6288f9ea7a52c966c8a238c9f4bdfe3)
2009-10-23 13:40:11 +00:00
097a05aab9 static content tagging (not finished yet)|update zh.po 2009-10-23 13:00:38 +00:00
0e5b2598fb Update the POs 2009-10-23 06:24:27 +00:00
4f492e33e6 Tagged ConfigKeyring/ConfigAdv (<input> not touched, Keyring needs word reordering not fully tagged) 2009-10-23 05:32:47 +00:00
1828b2bd17 tagged Configupdate/Tunnels (code inside <input> not touched!) 2009-10-23 05:07:16 +00:00
zzz
0c74e640df * Console:
- Don't hide link to configui.jsp for IE any more
      - Add lang selection on configui.jsp
      - Tag strings in configui.jsp
      - Load console_big.css if lang == zh
      - Add _x() tag for static iniitializers
      - HTML transitional input tags
2009-10-22 22:25:53 +00:00
zzz
ffd2721627 javadoc 2009-10-22 22:22:38 +00:00
zzz
f6ce4cb29f * Update: Better error message when .sud file not found or truncated
http://forum.i2p/viewtopic.php?t=3979
      The bug with the file going to the wrong place was fixed a couple months ago.
2009-10-22 22:21:55 +00:00
zzz
4863ef3360 * Certificate: Fix the (apparently unused) readBytes(byte[], int) method
for a null certificate - http://zzz.i2p/topics/388 - thanks HungryHobo
2009-10-22 22:20:50 +00:00
z3d
9f7807ee10 Classic theme: div.joblog h3 tweak to avoid breakage in logs and jobs pages. 2009-10-22 15:51:33 +00:00
z3d
b2285b0beb merge of '4cf77c9e1533ff7c4920a9d18ace7575a99d0bbc'
and '4e2465fc8dfc40cf276310eb917c3cef184db5cb'
2009-10-22 11:47:26 +00:00
z3d
8e4f4f82a8 UI layout cleanups and finessing. 2009-10-22 11:33:02 +00:00
db2158d4c1 translation revision 2009-10-22 07:42:47 +00:00
z3d
1c461bbeda Catch an errant <hr> in jobs.jsp; "backport" vertical sidebar space savings to classic theme. 2009-10-22 01:29:56 +00:00
z3d
0757f4f309 merge of '14fd58d7e574b7ae755514ce48508d9080b269d8'
and 'b09bd2e70d37e27a7f6e51afa4f1ae2d2298d30c'
2009-10-22 00:49:48 +00:00
z3d
a2f287cdfe Tidyups & more vertical spatial effiencies in the sidebar. 2009-10-22 00:23:17 +00:00
1ef448d518 chinese translation for the zh.po 2009-10-21 17:10:27 +00:00
z3d
f44b1a35bc Sidepanel space efficiencies; "paperclips" for index.jsp links; fix news.xml link. 2009-10-21 16:34:43 +00:00
zzz
26f02a4771 -4 2009-10-20 16:35:13 +00:00
zzz
dc3c730937 propagate from branch 'i2p.i2p.zzz.test' (head efc35e19029b7d92265f25eb024114737b6545e1)
to branch 'i2p.i2p' (head bbf149917e39bdd2f53246c238d440369498ae09)
2009-10-20 16:01:13 +00:00
zzz
77d45e7a3a stub for windows gettext script 2009-10-20 16:00:57 +00:00
zzz
45a59f009b add a common method for title formatting and translation 2009-10-20 12:12:26 +00:00
zzz
dc6d6ead69 fix bundle caching 2009-10-20 11:27:40 +00:00
zzz
27693826a2 summary bar post-refactor fixups 2009-10-19 21:40:14 +00:00
zzz
8a647b42d5 javadoc update 2009-10-19 21:38:37 +00:00
zzz
eba9f3c03b drop msgs expiring too far in the future 2009-10-19 21:37:59 +00:00
zzz
eacf46b367 remove some remnants of the pre-0.6.1.30 tunnel build method 2009-10-19 18:45:39 +00:00
zzz
83cacaad05 * summarynoframe.jsp:
- Refactor to SummaryBarRenderer (saves 100KB)
      - Add translate tags
      - Use context RNG for nonces
      - Transitional HTML style for input tags
2009-10-19 13:49:47 +00:00
zzz
cf10451d14 po script update, dont include java files in war 2009-10-19 13:37:13 +00:00
z3d
44069645df New formatting for news.xml; elliptical UI enhancements. 2009-10-19 12:34:19 +00:00
zzz
4497463778 * Router Console translation infrastructure:
- Persistent lang setting with routerconsole.lang=xx
      - Loading any page with ?lang=xx changes the persistent setting
      - Add a custom Jetty handler to load foo_xx.jsp if it
        exists for language xx. This is for jsp files with lots
        of text in them. Otherwise use inline translate methods.
        Not for included jsps.
      - Add a script to create and update messages_xx.po translation
        files, and create ResourceBundles from them
      - Add class to translate strings from cached ResourceBundles
      - Add translate wrappers to HelperBase, FormHandler, and *Renderer,
        so calls can be made from both jsp and java files
      - Add two example translations on configupdate.jsp - one in
        the jsp itself and one in the helper.
      - This is for strings in routerconsole only. Will be expanded
        to other webapps and the router later.
2009-10-18 14:06:07 +00:00
zzz
10b84418c3 move TunnelPoolManager renderStatusHTML to routerconsole 2009-10-17 23:49:59 +00:00
z3d
fadda4ceec More UI whitespace cleanups and other miscellaneous UI goodness. 2009-10-17 23:34:38 +00:00
zzz
011a32f741 move NetDb renderStatusHTML() to routerconsole 2009-10-17 23:16:53 +00:00
z3d
10bb3c100e Add some link bullet point graphics. 2009-10-17 07:08:36 +00:00
z3d
2738d5851d More UI whitespace removals and optimizations. 2009-10-17 07:04:40 +00:00
zzz
219095404a dont dump the whole JVM if we cant open the log file 2009-10-17 02:22:35 +00:00
zzz
001c361338 MessageHistory cleanups 2009-10-17 02:21:38 +00:00
zzz
e21a172e95 javadoc fix 2009-10-17 02:21:08 +00:00
z3d
4651b7007b Bump to -2. 2009-10-16 20:29:29 +00:00
z3d
5b4be5ba1b merge of '74266b0afe4ef1abef923c8389fb47263b9a39e1'
and '9a62d1aa11b74d835ec795c0a303bf5c2ebc2793'
2009-10-16 20:16:29 +00:00
z3d
9c2c90c0b1 Whitespace removals. 2009-10-16 20:01:18 +00:00
zzz
bdd0c3f961 -1 2009-10-16 15:08:27 +00:00
zzz
b7013361c2 propagate from branch 'i2p.i2p.zzz.test' (head 584fab1afc347099ea2fcbdcafa4a3dc4214d7dc)
to branch 'i2p.i2p' (head eb7f635432246f567a88babf08323105f364c80e)
2009-10-16 14:56:19 +00:00
zzz
f73b3e522b * NetDb: Rework part 1 of N:
- Flood only to those closest to the key
      - Java 5 fixups
2009-10-16 13:50:06 +00:00
zzz
fa6d17a1b8 * ProfileOrganizerRenderer:
- Move to routerconsole
      - Write directly to Writer for speed
2009-10-15 22:42:22 +00:00
z3d
c3e646ca22 Bump to -1, belatedly; more aesthetic nudges. 2009-10-14 17:25:29 +00:00
zzz
fdc9e11fb4 add TPB to i2psnark 2009-10-14 16:52:46 +00:00
zzz
a1ec838282 * oldconsole.jsp: Remove almost all of it, tweaks for tino
* Router: add router.hideFloodfillParticipant option for testing
2009-10-14 16:20:00 +00:00
zzz
7da46517ae slow down the volunteers again 2009-10-14 13:51:48 +00:00
zzz
d8e2939307 post-release cleanup 2009-10-13 14:13:16 +00:00
zzz
8cad72c654 two more test classes out of the lib 2009-10-13 14:12:00 +00:00
z3d
2cfc2bb60d merge of '11e1fae0346ea92d16925d6766a3d161ea7285c7'
and 'ca71a7d5f75cc879cfd2ba742bcc1d9baa6f9099'
2009-10-13 00:09:04 +00:00
z3d
1811e3b9cd Whitespace rationalization; theme enhancements; draft itoopie graphic for proxy errors. 2009-10-12 23:55:21 +00:00
699 changed files with 66870 additions and 26172 deletions

View File

@ -1,10 +1,17 @@
I2P source installation instructions
Prerequisites to build from source:
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
Apache Ant 1.7.0 or higher
Optional, For multilanguage support: The xgettext, msgfmt, and msgmerge tools installed
from the GNU gettext package http://www.gnu.org/software/gettext/
To build and install I2P from source, you must first build
and package up the appropriate installer by running:
ant pkg
This will produce a few key files:
* install.jar: the GUI and console installer
* i2pinstall.exe: the GUI and console installer wrapped for cross-platform execution
@ -18,9 +25,6 @@ Or run the GUI installer:
Or move the update file into an existing installation directory and restart.
You will need to have ant installed from http://ant.apache.org/
(1.7.0 or newer)
Supported JVMs:
Windows: Latest available from http://java.sun.com/ (1.5+ supported)
Linux: Latest available from http://java.sun.com/ (1.5+ supported)

View File

@ -80,9 +80,10 @@ Public domain except as listed below:
Installer:
Launch4j 2.0.RC3:
Copyright (C) 2005 Grzegorz Kowal
See licenses/LICENSE-GPLv2.txt
Launch4j 3.0.1:
Copyright (c) 2004, 2008 Grzegorz Kowal
See licenses/LICENSE-Launch4j.txt (in binary packages)
See installer/lib/launch4j/LICENSE.txt (in source packages)
The following projects are used by Launch4j...
MinGW binutils (http://www.mingw.org/)
@ -207,6 +208,9 @@ The following applications and libraries are not used or bundled in
binary packages, therefore the licenses are not included in binary
distributions. See the source package for the additional license information.
Admin Manager:
Public domain
Atalk:
Public domain

View File

@ -1,11 +1,13 @@
Prerequisites to build from source:
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
Apache Ant 1.7.0 or higher
Optional, For multilanguage support: The xgettext, msgfmt, and msgmerge tools installed
from the GNU gettext package http://www.gnu.org/software/gettext/
To build:
ant pkg
Run 'ant' with no arguments to see other build options.
See http://www.i2p2.de/download.html for installation instructions.
See INSTALL.txt or http://www.i2p2.de/download.html for installation instructions.
Documentation:
http://www.i2p2.de/

View File

@ -1,43 +1,155 @@
#!/bin/sh
#
#
# Now in the future we only need to look for '#I2P' and '#/I2P'
# for modifications to rc.local and rc.local_shutdown.
# I was a moron for not doing it this way in the first place :-) -- Sponge
#
#
touch /etc/rc.d/rc.local
touch /etc/rc.d/rc.local_shutdown
I2PRCA=`grep -c /etc/rc.d/rc.local -e i2p`
I2PRCB=`grep -c /etc/rc.d/rc.local_shutdown -e i2p`
echo
echo -n "Check 1: /etc/rc.d/rc.local "
I2PRCA=`grep -c /etc/rc.d/rc.local -e '/etc/rc.d/rc.i2p'`
if [ $I2PRCA -eq 0 ] ; then
echo '#I2P' >> /etc/rc.d/rc.local
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
echo "fi" >> /etc/rc.d/rc.local
echo "/etc/rc.d/rc.local modified."
echo '#/I2P' >> /etc/rc.d/rc.local
echo "modified."
else
echo "/etc/rc.d/rc.local looks OK"
echo -n "looks OK so far,"
# Fix old installs, or where people have modified.
echo -n " Check 1A: "
I2PRCC=`grep -c /etc/rc.d/rc.local -e 'i2p-\*\.tmp'`
if [ $I2PRCC -eq 0 ] ; then
DATA=$(cat /etc/rc.d/rc.local | sed -re 's/if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/#I2P\n\( cd \/tmp ; rm -Rf i2p-*.tmp \)\nif \[ -x \/etc\/rc.d\/rc.i2p \] ; then/')
echo "${DATA}" > /etc/rc.d/rc.local
echo -n "additional modifications applied,"
else
echo -n "looks OK so far,"
fi
echo -n " Check 1B: "
I2PRCE=`grep -c /etc/rc.d/rc.local -e 'i2p-\*\.tmp'`
if [ $I2PRCE -eq 0 ] ; then
DATATOP=$(cat /etc/rc.d/rc.local | sed -n '0,/i2p-\*\.tmp/p' | sed '$d' )
DATABOT=$(cat /etc/rc.d/rc.local | sed -n '/i2p-\*\.tmp/,$p' | sed -n '/^fi/,$p' | sed "1d")
echo "${DATATOP}" > /etc/rc.d/rc.local
echo '#I2P' >> /etc/rc.d/rc.local
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
echo "fi" >> /etc/rc.d/rc.local
echo '#/I2P' >> /etc/rc.d/rc.local
echo "${DATABOT}" >> /etc/rc.d/rc.local
echo -n "additional modifications applied,"
else
echo -n "looks ok so far,"
fi
echo -n " Check 1C: "
I2PRCF=`grep -c /etc/rc.d/rc.local -e '#/I2P'`
if [ $I2PRCF -eq 0 ] ; then
DATATOP=$(cat /etc/rc.d/rc.local | sed -n '0,/^#I2P/p' | sed '$d' )
DATABOT=$(cat /etc/rc.d/rc.local | sed -n '/^#I2P/,$p' | sed -n '/^fi/,$p' | sed "1d")
echo "${DATATOP}" > /etc/rc.d/rc.local
echo '#I2P' >> /etc/rc.d/rc.local
echo '( cd /tmp ; rm -Rf i2p-*.tmp )' >> /etc/rc.d/rc.local
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
echo "fi" >> /etc/rc.d/rc.local
echo '#/I2P' >> /etc/rc.d/rc.local
echo "${DATABOT}" >> /etc/rc.d/rc.local
echo -n "additional modifications applied,"
else
echo -n "looks ok so far,"
fi
echo " Done."
fi
echo -n "Check 2: /etc/rc.d/rc.local_shutdown "
I2PRCB=`grep -c /etc/rc.d/rc.local_shutdown -e '/etc/rc.d/rc.i2p'`
if [ $I2PRCB -eq 0 ] ; then
echo "#I2P" >> /etc/rc.d/rc.local_shutdown
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
echo "fi" >> /etc/rc.d/rc.local_shutdown
echo "/etc/rc.d/rc.local_shutdown modified."
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
echo "modified."
else
echo "/etc/rc.d/rc.local_shutdown looks OK"
echo -n "looks OK so far,"
# Fix old installs
echo -n " Check 1A: "
I2PRCG=`grep -c /etc/rc.d/rc.local_shutdown -e '#I2P'`
if [ $I2PRCG -eq 0 ] ; then
DATATOP=$(cat /etc/rc.d/rc.local_shutdown | sed -n '0,/^if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/p' | sed '$d' )
DATABOT=$(cat /etc/rc.d/rc.local_shutdown | sed -n '/^if \[ -x \/etc\/rc\.d\/rc\.i2p \] ; then/,$p' | sed -n '/^fi/,$p' | sed "1d")
echo "${DATATOP}" > /etc/rc.d/rc.local_shutdown
echo '#I2P' >> /etc/rc.d/rc.local_shutdown
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
echo "fi" >> /etc/rc.d/rc.local_shutdown
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
echo "${DATABOT}" >> /etc/rc.d/rc.local_shutdown
echo -n "additional modifications applied,"
else
echo -n "looks OK so far,"
fi
echo -n " Check 1B: "
I2PRCH=`grep -c /etc/rc.d/rc.local_shutdown -e '#/I2P'`
if [ $I2PRCH -eq 0 ] ; then
DATATOP=$(cat /etc/rc.d/rc.local_shutdown | sed -n '0,/^#I2P/p' | sed '$d' )
DATABOT=$(cat /etc/rc.d/rc.local_shutdown | sed -n '/^#I2P/,$p' | sed -n '/^fi/,$p' | sed "1d")
echo "${DATATOP}" > /etc/rc.d/rc.local_shutdown
echo '#I2P' >> /etc/rc.d/rc.local_shutdown
echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
echo "fi" >> /etc/rc.d/rc.local_shutdown
echo "#/I2P" >> /etc/rc.d/rc.local_shutdown
echo "${DATABOT}" >> /etc/rc.d/rc.local_shutdown
echo -n "additional modifications applied,"
else
echo -n "looks OK so far,"
fi
echo " Done."
fi
if [ -f /etc/rc.d/rc.i2p ] ; then
if [ -x /etc/rc.d/rc.i2p ] ; then
chmod +x /etc/rc.d/rc.i2p.new
fi
echo
# Hopefully get admin's attention.
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -e "\007" ; sleep 0.3
echo "It apears that you already have /etc/rc.d/rc.i2p"
echo "You may wish to replace it with /etc/rc.d/rc.i2p.new"
echo
echo "You should replace it with /etc/rc.d/rc.i2p.new as soon as possible"
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -ne "\007" ; sleep 0.3
echo -e "\007" ; sleep 0.3
else
mv /etc/rc.d/rc.i2p.new /etc/rc.d/rc.i2p
echo
echo "Installation finished. The i2p start/stop script has been"
echo "installed on /etc/rc.d directory. You should chmod +x"
echo "installed in /etc/rc.d . You should chmod +x"
echo '/etc/rc.d/rc.i2p to start it on boot.'
echo
fi

View File

@ -1,46 +1,57 @@
#!/bin/sh
# Heavily based on the Slackware 12.1 SlackBuild
# Slackware build script for i2p
#
# Heavily based on the Slackware 12.2 SlackBuild
# Slackware build script for I2P
#
# PLEASE READ THIS:
# Probably you will never have to update i2p packages with upgradepkg,
# just because i2p have an auto-update function.
# How to start i2p:
# After installpkg command, doinst.sh will execute a postinstallation script
# needed by i2p. After that you have to chmod +x /etc/rc.d/rc.i2p and start
# i2p service with /etc/rc.d/rc.i2p start.
# How to start I2P:
# After installpkg command, doinst.sh will execute a post-installation script
# needed by I2P. After that you have to chmod +x /etc/rc.d/rc.i2p and start
# I2P service with /etc/rc.d/rc.i2p start.
#
# Now tell your browser to user this proxy: localhost on port 4444 and open
# this page: http://localhost:7657/index.jsp
# Here you can configure i2p, watch network status and navigate anonimously.
#
# Here you can configure I2P, watch network status and navigate anonimously.
# It's suggested to subscribe to various dns host, like i2host.i2p
# For any additional information, visit i2host.i2p and forum.i2p
#
CWD=$(pwd)
TMP=/tmp
PKG=/$TMP/package-base-i2p
rm -rf $PKG
mkdir -p $PKG
# put here installation dir, without first and last /
# es: usr/local
NAME=i2p-base
VERSION=0.0.1
VERSION=0.0.2
BUILD=1sponge
ARCH=noarch
INSTALL_DIR=opt
# Less than slackware 13?
SLKPLT=$(cat /etc/slackware-version | sed -re "s/(Slackware )([0-9]*)(.*)/\2/")
if [ $SLKPLT -lt 13 ] ; then
EXT=tgz
else
EXT=txz
fi
rm -rf $PKG
mkdir -p $PKG
cd $PKG
chown -R root:root .
mkdir -p $PKG/etc/rc.d
mkdir -p $PKG/install
sed "s|directory|/$INSTALL_DIR/i2p/i2prouter|g" $CWD/rc.i2p_def > $PKG/etc/rc.d/rc.i2p.new
sed "s|directory|/$INSTALL_DIR/i2p/i2prouter|g" "$CWD/rc.i2p_def" > $PKG/etc/rc.d/rc.i2p.new
chmod 644 $PKG/etc/rc.d/rc.i2p.new
sed "s|directory|/$INSTALL_DIR/i2p/|g" $CWD/doinst.sh > $PKG/install/doinst.sh
cat $CWD/slack-desc > $PKG/install/slack-desc
cat "$CWD/doinst.sh" > $PKG/install/doinst.sh
cat "$CWD/slack-desc" > $PKG/install/slack-desc
cd $PKG
#
# Not really that important to exec this.
#requiredbuilder -v -y -s $CWD $PKG
# Not really that important to exec this
# as there aren't any deps we don't know.
#
cat $CWD/slack-required > $PKG/install/slack-required
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
# requiredbuilder -v -y -s $CWD $PKG
#
cat "$CWD/slack-required" > $PKG/install/slack-required
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.$EXT

View File

@ -9,6 +9,22 @@ i2p_stop() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory stop )"
}
i2p_restart() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory restart)"
}
i2p_status() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory status )"
}
i2p_console() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory console )"
}
i2p_dump() {
/bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory dump )"
}
case "$1" in
'start')
i2p_start
@ -17,11 +33,19 @@ case "$1" in
i2p_stop
;;
'restart')
i2p_stop
i2p_start
i2p_restart
;;
'status')
i2p_status
;;
'console')
i2p_console
;;
'dump')
i2p_dump
;;
*)
echo "usage $0 start|stop|restart"
echo "usage $0 start|stop|restart|status|console|dump"
;;
esac

View File

@ -1,28 +1,35 @@
#!/bin/sh
# Heavily based on the Slackware 12.1 SlackBuild
# Slackware build script for i2p
#
# Heavily based on the Slackware 12.2 SlackBuild
# Slackware build script for I2P
#
# PLEASE READ THIS:
# Probably you will never have to update i2p packages with upgradepkg,
# just because i2p have an auto-update function.
# How to start i2p:
# After installpkg command, doinst.sh will execute a postinstallation script
# needed by i2p. After that you have to chmod +x /etc/rc.d/rc.i2p and start
# i2p service with /etc/rc.d/rc.i2p start.
# Now tell your browser to user this proxy: localhost on port 4444 and open
# this page: http://localhost:7657/index.jsp
# Here you can configure i2p, watch network status and navigate anonimously.
# It's suggested to subscribe to various dns host, like i2host.i2p
# For any additional information, visit i2host.i2p and forum.i2p
# Probably you will never have to update I2P packages with upgradepkg,
# just because I2P has an auto-update function.
# Really you should not ever use any "upgrade" method.
#
# The correct way to upgrade is to:
# 1: install the upgrade
# 2: remove the old package
#
# It is a terrible shame that upgradepkg doesn't do this, infact,
# it would actually be the correct way for *any* package!
#
#
BUILD=1sponge
# put here installation dir, without first and last /
# eg: usr/local
INSTALL_DIR=opt
NAME=i2p
ARCH=noarch
# Less than slackware 13?
SLKPLT=$(cat /etc/slackware-version | sed -re "s/(Slackware )([0-9]*)(.*)/\2/")
if [ $SLKPLT -lt 13 ] ; then
EXT=tgz
else
EXT=txz
fi
#
# This mess is here due to the totally moronic way i2p does versioning.
@ -117,7 +124,7 @@ cd $PKG
# requiredbuilder fucks up REALLY bad, and thinks java is perl?!
# It also did not catch the shell requirements! BOOOOOOOOOOO! HISSSSSSSS!
#
#requiredbuilder -v -y -s $CWD $PKG
# requiredbuilder -v -y -s $CWD $PKG
#
cat $CWD/slack-required > $PKG/install/slack-required
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.$EXT

View File

@ -1,9 +1,13 @@
These instructions are for the 1.5 SDK.
These instructions are for the 1.5 Android SDK.
The build file is not compatible with the 1.1 SDK any more.
1.6 and 2.0 SDKs are untested.
#Unzip the android SDK in ../../
#So then the android tools will be in ../../android-sdk-linux_x86-1.5_r2/tools/
# create a file local.properties with the following line:
# sdk-location=/path/to/your/android-sdk-linux_x86-1.5_r2
#then build the android apk file:
ant debug

View File

@ -71,4 +71,44 @@
nbproject/build-impl.xml file.
-->
<target depends="jar" description="Build BOB into a SINGLE JAR." name="onejar">
<!-- Make needed working dirs -->
<mkdir dir="${dist.dir}/lib" />
<mkdir dir="${dist.dir}/classes" />
<!-- Copy jars -->
<copy todir="${dist.dir}/lib" flatten="true" >
<path>
<pathelement path="${javac.classpath}" />
</path>
</copy>
<copy todir="${dist.dir}/lib" file="../../installer/lib/jbigi/jbigi.jar" />
<!-- Extract the classes inside the jar files -->
<unjar dest="${dist.dir}/classes" >
<fileset dir="${dist.dir}/lib" >
<include name="**/*.jar" />
</fileset>
</unjar>
<!-- Recombine the classes into a new jar file -->
<jar jarfile="${dist.dir}/lib/all-in-one.jar" >
<fileset dir="${dist.dir}/classes" />
</jar>
<!-- Clean up work area -->
<delete dir="${dist.dir}/classes" followsymlinks="false" includeemptydirs="true"/>
<!-- Make the single jar file -->
<jar jarfile="dist/BOB-one.jar" >
<zipfileset src="${dist.jar}" excludes="META-INF/*" />
<zipfileset src="${dist.dir}/lib/all-in-one.jar" excludes="**/META-INF/*" />
<manifest>
<attribute name="Main-Class" value="net.i2p.BOB.Main" />
</manifest>
</jar>
<!-- Clean up the fake jar file -->
<delete file="${dist.dir}/lib/all-in-one.jar" />
</target>
</project>

View File

@ -3,5 +3,6 @@ do.depend=false
do.jar=true
javac.debug=true
javadoc.preview=true
jaxbwiz.endorsed.dirs=/usr/local/netbeans-6.8/ide12/modules/ext/jaxb/api
jaxws.endorsed.dir=/usr/local/netbeans-6.5/java2/modules/ext/jaxws21/api:/usr/local/netbeans-6.5/ide10/modules/ext/jaxb/api
user.properties.file=/root/.netbeans/6.5/build.properties

View File

@ -1,7 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
<file>file:/usblv/NetBeansProjects/wi2p.i2p/apps/BOB/src/net/i2p/BOB/BOB.java</file>
</open-files>
</project-private>

View File

@ -1,5 +1,6 @@
application.homepage=http://bob.i2p/
application.title=BOB
application.vendor=root
application.vendor=Sponge
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=8
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=8
@ -11,6 +12,7 @@ build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
@ -23,6 +25,7 @@ debug.test.classpath=\
dist.dir=dist
dist.jar=${dist.dir}/BOB.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
file.reference.i2p.jar=../../core/java/build/i2p.jar
@ -33,7 +36,7 @@ file.reference.router.jar=../../router/java/build/router.jar
file.reference.streaming.jar=../streaming/java/build/streaming.jar
file.reference.wrapper.jar=../../installer/lib/wrapper/linux/wrapper.jar
includes=**
jar.compress=false
jar.compress=true
javac.classpath=\
${file.reference.router.jar}:\
${file.reference.i2ptunnel.jar}:\
@ -63,8 +66,9 @@ javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
jnlp.codebase.type=local
jnlp.codebase.url=file:/root/NetBeansProjects/i2p.i2p/apps/BOB/dist/
jnlp.codebase.url=file:/usblv/NetBeansProjects/i2p.i2p/apps/BOB/dist
jnlp.descriptor=application
jnlp.enabled=false
jnlp.offline-allowed=false

View File

@ -256,11 +256,13 @@ public class BOB {
listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
Socket server = null;
listener.setSoTimeout(500); // .5 sec
while (spin.get()) {
//DoCMDS connection;
try {
server = listener.accept();
server.setKeepAlive(true);
g = true;
} catch (ConnectException ce) {
g = false;

View File

@ -50,7 +50,7 @@ public class DoCMDS implements Runnable {
// FIX ME
// I need a better way to do versioning, but this will do for now.
public static final String BMAJ = "00", BMIN = "00", BREV = "08", BEXT = "";
public static final String BMAJ = "00", BMIN = "00", BREV = "0B", BEXT = "";
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
private Socket server;
private Properties props;
@ -691,6 +691,7 @@ public class DoCMDS implements Runnable {
try {
prikey = new ByteArrayOutputStream();
prikey.write(net.i2p.data.Base64.decode(Arg));
d = new Destination();
d.fromBase64(Arg);
} catch (Exception ex) {
Arg = "";

View File

@ -60,20 +60,9 @@ public class I2Plistener implements Runnable {
this._log = _log;
this.socketManager = S;
this.serverSocket = SS;
// tgwatch = 1;
this.lives = lives;
}
private void rlock() throws Exception {
database.getReadLock();
info.getReadLock();
}
private void runlock() throws Exception {
database.releaseReadLock();
info.releaseReadLock();
}
/**
* Simply listen on I2P port, and thread connections
*
@ -83,34 +72,31 @@ public class I2Plistener implements Runnable {
I2PSocket sessSocket = null;
int conn = 0;
try {
die:
{
try {
serverSocket.setSoTimeout(50);
while (lives.get()) {
try {
sessSocket = serverSocket.accept();
g = true;
} catch (ConnectException ce) {
g = false;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
g = false;
conn++;
// toss the connection to a new thread.
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
t.start();
}
try {
serverSocket.setSoTimeout(50);
while (lives.get()) {
try {
sessSocket = serverSocket.accept();
g = true;
} catch (ConnectException ce) {
g = false;
} catch (SocketTimeoutException ste) {
g = false;
}
} catch (I2PException e) {
// bad shit
System.out.println("Exception " + e);
if (g) {
g = false;
conn++;
// toss the connection to a new thread.
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
t.start();
}
}
} catch (I2PException e) {
// bad shit
System.out.println("Exception " + e);
}
} finally {
try {

View File

@ -102,6 +102,7 @@ public class I2PtoTCP implements Runnable {
break die;
}
sock = new Socket(host, port);
sock.setKeepAlive(true);
// make readers/writers
in = sock.getInputStream();
out = sock.getOutputStream();

View File

@ -104,10 +104,10 @@ public class MUXlisten implements Runnable {
this.database.releaseReadLock();
this.info.releaseReadLock();
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
if (this.come_in) {
this.listener = new ServerSocket(port, backlog, host);
}
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
// I2PException, IOException, RuntimeException
// To bad we can't just catch and enumerate....
// } catch (I2PException e) {
@ -141,8 +141,6 @@ public class MUXlisten implements Runnable {
this.info.add("STARTING", new Boolean(false));
this.info.releaseWriteLock();
this.database.releaseWriteLock();
// throw new Exception(e);
// Debugging, I guess.
e.printStackTrace();
throw new RuntimeException(e);
}

View File

@ -78,16 +78,20 @@ public class TCPio implements Runnable {
* --Sponge
*
* Tested with 128 bytes, and there was no performance gain.
* 8192 bytes did lower load average across many connections.
* Should I raise it higer? The correct thing to do would be to
* override... perhaps use NTCP, but I2P's streaming lib lacks
* anything NTCP compatable.
*
* --Sponge
*/
int b;
byte a[] = new byte[1];
byte a[] = new byte[8192];
try {
try {
while (lives.get()) {
b = Ain.read(a, 0, 1);
b = Ain.read(a, 0, 8192);
if (b > 0) {
Aout.write(a, 0, b);
} else if (b == 0) {

View File

@ -64,16 +64,6 @@ public class TCPlistener implements Runnable {
this.lives = lives;
}
private void rlock() throws Exception {
database.getReadLock();
info.getReadLock();
}
private void runlock() throws Exception {
database.releaseReadLock();
info.releaseReadLock();
}
/**
* Simply listen on TCP port, and thread connections
*
@ -81,30 +71,28 @@ public class TCPlistener implements Runnable {
public void run() {
boolean g = false;
int conn = 0;
Socket server = null;
try {
die:
{
try {
Socket server = new Socket();
listener.setSoTimeout(50); // We don't block, we cycle and check.
while (lives.get()) {
try {
server = listener.accept();
g = true;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
conn++;
// toss the connection to a new thread.
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
t.start();
g = false;
}
try {
listener.setSoTimeout(50); // We don't block, we cycle and check.
while (lives.get()) {
try {
server = listener.accept();
server.setKeepAlive(true);
g = true;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
conn++;
// toss the connection to a new thread.
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
t.start();
g = false;
}
} catch (IOException ioe) {
}
} catch (IOException ioe) {
}
} finally {
try {

View File

@ -146,8 +146,14 @@ public class TCPtoI2P implements Runnable {
input = line.toLowerCase();
Destination dest = null;
if (input.endsWith(".i2p")) {
dest = I2PTunnel.destFromName(input);
line = dest.toBase64();
try {
dest = I2PTunnel.destFromName(input);
line = dest.toBase64();
} catch (NullPointerException npe) {
// Could not find the destination!?
Emsg("Can't find destination: " + input, out);
return;
}
}
dest = new Destination();
dest.fromBase64(line);

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2004 Ragnarok
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
import javax.servlet.GenericServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* A wrapper for addressbook to allow it to be started as a web application.
*
* @author Ragnarok
*
*/
public class Servlet extends GenericServlet {
/* (non-Javadoc)
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
public void service(ServletRequest request, ServletResponse response) {
}
/* (non-Javadoc)
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
@Override
public void init(ServletConfig config) {
try {
super.init(config);
} catch (ServletException exp) {
}
String[] args = new String[1];
args[0] = config.getInitParameter("home");
DaemonThread thread = new DaemonThread(args);
thread.setDaemon(true);
thread.setName("Addressbook");
thread.start();
System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
System.out.println("INFO: config root under " + args[0]);
}
}

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
package net.i2p.addressbook;
import java.io.File;
import java.io.IOException;
@ -193,7 +193,8 @@ public class AddressBook {
(! host.endsWith(".router.i2p")) &&
(! host.endsWith(".console.i2p")) &&
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AAAA")) ||
// null cert ends with AAAA but other zero-length certs would be AA
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AA")) ||
(dest.length() > MIN_DEST_LENGTH && dest.length() <= MAX_DEST_LENGTH)) &&
dest.replaceAll("[a-zA-Z0-9~-]", "").length() == 0
;

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
package net.i2p.addressbook;
import java.io.BufferedReader;
import java.io.BufferedWriter;

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
package net.i2p.addressbook;
import java.io.File;
import java.util.HashMap;

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
package net.i2p.addressbook;
/**
* A thread that waits five minutes, then runs the addressbook daemon.

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
package net.i2p.addressbook;
import java.io.BufferedWriter;
import java.io.File;

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2004 Ragnarok
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package net.i2p.addressbook;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* A wrapper for addressbook to allow it to be started as a web application.
*
* This was a GenericServlet, we make it an HttpServlet solely to provide a hook
* for SusiDNS to wake us up when the subscription list changes.
*
* @author Ragnarok
*
*/
public class Servlet extends HttpServlet {
private Thread thread;
private String nonce;
private static final String PROP_NONCE = "addressbook.nonce";
/**
* Hack to allow susidns to kick the daemon when the subscription list changes.
* URL must be /addressbook/ with wakeup param set, and nonce param set from system property.
*
* (non-Javadoc)
* see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
//System.err.println("Got request nonce = " + request.getParameter("nonce"));
if (this.thread != null && request.getParameter("wakeup") != null &&
this.nonce != null && this.nonce.equals(request.getParameter("nonce"))) {
//System.err.println("Sending interrupt");
this.thread.interrupt();
// no output
} else {
PrintWriter out = response.getWriter();
out.write("I2P addressbook OK");
}
}
/* (non-Javadoc)
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
@Override
public void init(ServletConfig config) {
try {
super.init(config);
} catch (ServletException exp) {
System.err.println("Addressbook init exception: " + exp);
}
this.nonce = "" + Math.abs((new Random()).nextLong());
// put the nonce where susidns can get it
System.setProperty(PROP_NONCE, this.nonce);
String[] args = new String[1];
args[0] = config.getInitParameter("home");
this.thread = new DaemonThread(args);
this.thread.setDaemon(true);
this.thread.setName("Addressbook");
this.thread.start();
System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
//System.out.println("INFO: config root under " + args[0]);
}
}

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
package net.i2p.addressbook;
/**
* A subscription to a remote address book.

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
package net.i2p.addressbook;
import java.util.Iterator;
import java.util.List;

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package addressbook;
package net.i2p.addressbook;
import java.io.File;
import java.io.IOException;

View File

@ -6,11 +6,17 @@
<web-app>
<servlet>
<servlet-name>addressbook</servlet-name>
<servlet-class>addressbook.Servlet</servlet-class>
<servlet-class>net.i2p.addressbook.Servlet</servlet-class>
<init-param>
<param-name>home</param-name>
<param-value>./addressbook</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
<servlet-mapping>
<servlet-name>addressbook</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

View File

@ -0,0 +1,17 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
# zzz - public domain
#
## launching sh.exe with -login parameter will open a shell with the current path always pointing to \bin\
## need to cd into our orignal path - where we call sh.exe from.
cd $CALLFROM
## echo $PWD
## except this everything is the same with bundle-message.sh
## walking - public domain :-D
source bundle-messages.sh $PARAS

View File

@ -37,7 +37,7 @@
</javac>
</target>
<target name="jar" depends="builddep, compile">
<jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/I2PSnarkServlet*.class">
<jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/I2PSnarkServlet*.class **/messages_*.class">
<manifest>
<attribute name="Main-Class" value="org.klomp.snark.Snark" />
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
@ -51,12 +51,44 @@
- So we must continue to duplicate everything in the war.
<classes dir="./build/obj" includes="**/I2PSnarkServlet*.class" />
-->
<target name="war" depends="jar">
<target name="war" depends="jar, bundle">
<war destfile="../i2psnark.war" webxml="../web.xml">
<classes dir="./build/obj" includes="**/*.class" excludes="**/RunStandalone.class" />
</war>
</target>
<target name="bundle" depends="compile">
<!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="false" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
</exec>
</target>
<target name="poupdate" depends="compile">
<!-- Update the messages_*.po files. -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="true" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
<arg value="-p" />
</exec>
</target>
<target name="standalone" depends="standalone_prep">
<zip destfile="i2psnark-standalone.zip">
<zipfileset dir="./dist/" prefix="i2psnark/" />
@ -95,9 +127,7 @@
<delete dir="./dist" />
</target>
<target name="cleandep" depends="clean">
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
<target name="distclean" depends="clean">
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
</project>

View File

@ -0,0 +1,26 @@
@echo off
set Callfrom=%cd%
set Paras=%1
rem before calling make sure you have msys and mingw 's "bin" path
rem in your current searching path
rem type "set path" to check
if not exist ..\locale\*.only goto updateALL
rem put a messages_xx.only(eg messages_zh.only) into locale folder
rem this script will only touch the po file(eg zh) you specified, leaving other po files untact.
for %%i in (..\locale\*.only) do set PO=%%~ni
echo [Notice] Yu choose to Ony update the choosen file: %PO%.po
for %%i in (..\locale\*.po) do if not %%~ni==%PO% ren %%i %%~ni.po-
call sh --login %cd%\bmsg.sh
for %%i in (..\locale\*.po-) do if not %%~ni==%PO% ren %%i %%~ni.po
goto end
:updateALL
call sh --login %cd%\bmsg.sh
:end
echo End of Message Bundling

View File

@ -0,0 +1,85 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
#
# usage:
# bundle-messages.sh (generates the resource bundle from the .po file)
# bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle)
#
# zzz - public domain
#
CLASS=org.klomp.snark.web.messages
TMPFILE=build/javafiles.txt
export TZ=UTC
if [ "$1" = "-p" ]
then
POUPDATE=1
fi
# add ../java/ so the refs will work in the po file
JPATHS="../java/src"
for i in ../locale/messages_*.po
do
# get language
LG=${i#../locale/messages_}
LG=${LG%.po}
if [ "$POUPDATE" = "1" ]
then
# make list of java files newer than the .po file
find $JPATHS -name *.java -newer $i > $TMPFILE
fi
if [ -s build/obj/org/klomp/snark/web/messages_$LG.class -a \
build/obj/org/klomp/snark/web/messages_$LG.class -nt $i -a \
! -s $TMPFILE ]
then
continue
fi
if [ "$POUPDATE" = "1" ]
then
echo "Updating the $i file from the tags..."
# extract strings from java and jsp files, and update messages.po files
# translate calls must be one of the forms:
# _("foo")
# _x("foo")
# To start a new translation, copy the header from an old translation to the new .po file,
# then ant distclean poupdate.
find $JPATHS -name *.java > $TMPFILE
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 \
--keyword=_ --keyword=_x \
-o ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - xgettext failed, not updating translations'
rm -f ${i}t
break
fi
msgmerge -U --backup=none $i ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - msgmerge failed, not updating translations'
rm -f ${i}t
break
fi
rm -f ${i}t
# so we don't do this again
touch $i
fi
echo "Generating ${CLASS}_$LG ResourceBundle..."
# convert to class files in build/obj
msgfmt --java --statistics -r $CLASS -l $LG -d build/obj $i
if [ $? -ne 0 ]
then
echo 'Warning - msgfmt failed, not updating translations'
break
fi
done
rm -f $TMPFILE
# todo: return failure
exit 0

View File

@ -28,6 +28,7 @@ import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.Translate;
/**
* I2P specific helpers for I2PSnark
@ -402,4 +403,32 @@ public class I2PSnarkUtil {
break;
}
}
private static final String BUNDLE_NAME = "org.klomp.snark.web.messages";
/** lang in routerconsole.lang property, else current locale */
public String getString(String key) {
return Translate.getString(key, _context, BUNDLE_NAME);
}
/**
* translate a string with a parameter
* This is a lot more expensive than getString(s, ctx), so use sparingly.
*
* @param s string to be translated containing {0}
* The {0} will be replaced by the parameter.
* Single quotes must be doubled, i.e. ' -> '' in the string.
* @param o parameter, not translated.
* To tranlslate parameter also, use _("foo {0} bar", _("baz"))
* Do not double the single quotes in the parameter.
* Use autoboxing to call with ints, longs, floats, etc.
*/
public String getString(String s, Object o) {
return Translate.getString(s, o, _context, BUNDLE_NAME);
}
/** {0} and {1} */
public String getString(String s, Object o, Object o2) {
return Translate.getString(s, o, o2, _context, BUNDLE_NAME);
}
}

View File

@ -105,8 +105,8 @@ class PeerCheckerTask extends TimerTask
peer.resetCounters();
_util.debug(peer + ":", Snark.DEBUG);
_util.debug(" ul: " + upload/KILOPERSECOND
+ " dl: " + download/KILOPERSECOND
_util.debug(" ul: " + upload*1024/KILOPERSECOND
+ " dl: " + download*1024/KILOPERSECOND
+ " i: " + peer.isInterested()
+ " I: " + peer.isInteresting()
+ " c: " + peer.isChoking()

View File

@ -236,10 +236,21 @@ public class PeerCoordinator implements PeerListener
{
synchronized(peers)
{
return !halted && peers.size() < _util.getMaxConnections();
return !halted && peers.size() < getMaxConnections();
}
}
/** reduce max if huge pieces to keep from ooming */
private int getMaxConnections() {
int size = metainfo.getPieceLength(0);
int max = _util.getMaxConnections();
if (size <= 1024*1024)
return max;
if (size <= 2*1024*1024)
return (max + 1) / 2;
return (max + 3) / 4;
}
public boolean halted() { return halted; }
public void halt()
@ -294,7 +305,7 @@ public class PeerCoordinator implements PeerListener
peer.disconnect(false); // Don't deregister this connection/peer.
}
// This is already checked in addPeer() but we could have gone over the limit since then
else if (peers.size() >= _util.getMaxConnections())
else if (peers.size() >= getMaxConnections())
{
if (_log.shouldLog(Log.WARN))
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
@ -350,7 +361,7 @@ public class PeerCoordinator implements PeerListener
peersize = peers.size();
// This isn't a strict limit, as we may have several pending connections;
// thus there is an additional check in connected()
need_more = (!peer.isConnected()) && peersize < _util.getMaxConnections();
need_more = (!peer.isConnected()) && peersize < getMaxConnections();
// Check if we already have this peer before we build the connection
Peer old = peerIDInList(peer.getPeerID(), peers);
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
@ -378,7 +389,7 @@ public class PeerCoordinator implements PeerListener
if (peer.isConnected())
_log.info("Add peer already connected: " + peer);
else
_log.info("Connections: " + peersize + "/" + _util.getMaxConnections()
_log.info("Connections: " + peersize + "/" + getMaxConnections()
+ " not accepting extra peer: " + peer);
}
return false;
@ -405,7 +416,7 @@ public class PeerCoordinator implements PeerListener
count++;
if (uploaders < maxUploaders)
{
if (!peer.isChoked())
if (peer.isInteresting() && !peer.isChoked())
interested.add(unchokedCount++, peer);
else
interested.add(peer);

View File

@ -20,6 +20,7 @@ import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.OrderedProperties;
/**
* Manage multiple snarks
@ -80,7 +81,7 @@ public class SnarkManager implements Snark.CompleteListener {
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util);
int minutes = getStartupDelayMinutes();
_messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
_messages.add(_("Adding torrents in {0} minutes", minutes));
I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
monitor.setDaemon(true);
monitor.start();
@ -126,7 +127,7 @@ public class SnarkManager implements Snark.CompleteListener {
/** null to set initial defaults */
public void loadConfig(String filename) {
if (_config == null)
_config = new Properties();
_config = new OrderedProperties();
if (filename != null) {
File cfg = new File(filename);
if (!cfg.isAbsolute())
@ -216,6 +217,7 @@ public class SnarkManager implements Snark.CompleteListener {
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers) {
boolean changed = false;
if (eepHost != null) {
// unused, we use socket eepget
int port = _util.getEepProxyPort();
try { port = Integer.parseInt(eepPort); } catch (NumberFormatException nfe) {}
String host = _util.getEepProxyHost();
@ -236,9 +238,9 @@ public class SnarkManager implements Snark.CompleteListener {
_util.setMaxUploaders(limit);
changed = true;
_config.setProperty(PROP_UPLOADERS_TOTAL, "" + limit);
addMessage("Total uploaders limit changed to " + limit);
addMessage(_("Total uploaders limit changed to {0}", limit));
} else {
addMessage("Minimum total uploaders limit is " + Snark.MIN_TOTAL_UPLOADERS);
addMessage(_("Minimum total uploaders limit is {0}", Snark.MIN_TOTAL_UPLOADERS));
}
}
}
@ -250,9 +252,9 @@ public class SnarkManager implements Snark.CompleteListener {
_util.setMaxUpBW(limit);
changed = true;
_config.setProperty(PROP_UPBW_MAX, "" + limit);
addMessage("Up BW limit changed to " + limit + "KBps");
addMessage(_("Up BW limit changed to {0}KBps", limit));
} else {
addMessage("Minimum Up BW limit is " + MIN_UP_BW + "KBps");
addMessage(_("Minimum up bandwidth limit is {0}KBps", MIN_UP_BW));
}
}
}
@ -296,27 +298,27 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
if (snarksActive) {
addMessage("Cannot change the I2CP settings while torrents are active");
addMessage(_("Cannot change the I2CP settings while torrents are active"));
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
+ "] oldOpts [" + oldOpts + "]");
} else {
if (_util.connected()) {
_util.disconnect();
addMessage("Disconnecting old I2CP destination");
addMessage(_("Disconnecting old I2CP destination"));
}
Properties p = new Properties();
p.putAll(opts);
addMessage("I2CP settings changed to " + i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")");
addMessage(_("I2CP settings changed to {0}", i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")"));
_util.setI2CPConfig(i2cpHost, port, p);
boolean ok = _util.connect();
if (!ok) {
addMessage("Unable to connect with the new settings, reverting to the old I2CP settings");
addMessage(_("Unable to connect with the new settings, reverting to the old I2CP settings"));
_util.setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
ok = _util.connect();
if (!ok)
addMessage("Unable to reconnect with the old settings!");
addMessage(_("Unable to reconnect with the old settings!"));
} else {
addMessage("Reconnected on the new I2CP destination");
addMessage(_("Reconnected on the new I2CP destination"));
_config.setProperty(PROP_I2CP_HOST, i2cpHost.trim());
_config.setProperty(PROP_I2CP_PORT, "" + port);
_config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim());
@ -327,7 +329,7 @@ public class SnarkManager implements Snark.CompleteListener {
Snark snark = getTorrent(name);
if ( (snark != null) && (snark.acceptor != null) ) {
snark.acceptor.restart();
addMessage("I2CP listener restarted for " + snark.meta.getName());
addMessage(_("I2CP listener restarted for \"{0}\"", snark.meta.getName()));
}
}
}
@ -337,26 +339,32 @@ public class SnarkManager implements Snark.CompleteListener {
}
if (shouldAutoStart() != autoStart) {
_config.setProperty(PROP_AUTO_START, autoStart + "");
addMessage("Adjusted autostart to " + autoStart);
if (autoStart)
addMessage(_("Enabled autostart"));
else
addMessage(_("Disabled autostart"));
changed = true;
}
if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
_config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + "");
addMessage((useOpenTrackers ? "En" : "Dis") + "abled open trackers - torrent restart required to take effect.");
if (useOpenTrackers)
addMessage(_("Enabled open trackers - torrent restart required to take effect."));
else
addMessage(_("Disabled open trackers - torrent restart required to take effect."));
changed = true;
}
if (openTrackers != null) {
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(_util.getOpenTrackerString())) {
_config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim());
_util.setOpenTrackerString(openTrackers);
addMessage("Open Tracker list changed - torrent restart required to take effect.");
addMessage(_("Open Tracker list changed - torrent restart required to take effect."));
changed = true;
}
}
if (changed) {
saveConfig();
} else {
addMessage("Configuration unchanged.");
addMessage(_("Configuration unchanged."));
}
}
@ -366,7 +374,7 @@ public class SnarkManager implements Snark.CompleteListener {
DataHelper.storeProps(_config, _configFile);
}
} catch (IOException ioe) {
addMessage("Unable to save the config to '" + _configFile.getAbsolutePath() + "'.");
addMessage(_("Unable to save the config to {0}", _configFile.getAbsolutePath()));
}
}
@ -384,10 +392,10 @@ public class SnarkManager implements Snark.CompleteListener {
public void addTorrent(String filename) { addTorrent(filename, false); }
public void addTorrent(String filename, boolean dontAutoStart) {
if ((!dontAutoStart) && !_util.connected()) {
addMessage("Connecting to I2P");
addMessage(_("Connecting to I2P"));
boolean ok = _util.connect();
if (!ok) {
addMessage("Error connecting to I2P - check your I2CP settings!");
addMessage(_("Error connecting to I2P - check your I2CP settings!"));
return;
}
}
@ -396,7 +404,7 @@ public class SnarkManager implements Snark.CompleteListener {
filename = sfile.getCanonicalPath();
} catch (IOException ioe) {
_log.error("Unable to add the torrent " + filename, ioe);
addMessage("ERR: Could not add the torrent '" + filename + "': " + ioe.getMessage());
addMessage(_("Error: Could not add the torrent {0}", filename) + ": " + ioe.getMessage());
return;
}
File dataDir = getDataDir();
@ -435,7 +443,7 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
} catch (IOException ioe) {
addMessage("Torrent in " + sfile.getName() + " is invalid: " + ioe.getMessage());
addMessage(_("Torrent in \"{0}\" is invalid", sfile.getName()) + ": " + ioe.getMessage());
if (sfile.exists())
sfile.delete();
return;
@ -450,9 +458,9 @@ public class SnarkManager implements Snark.CompleteListener {
File f = new File(filename);
if (!dontAutoStart && shouldAutoStart()) {
torrent.startTorrent();
addMessage("Torrent added and started: '" + f.getName() + "'.");
addMessage(_("Torrent added and started: \"{0}\"", f.getName()));
} else {
addMessage("Torrent added: '" + f.getName() + "'.");
addMessage(_("Torrent added: \"{0}\"", f.getName()));
}
}
@ -548,15 +556,19 @@ public class SnarkManager implements Snark.CompleteListener {
// basic validation of url
if ((!announce.startsWith("http://")) ||
(announce.indexOf(".i2p/") < 0)) // need to do better than this
return "Non-i2p tracker in " + info.getName() + ", deleting it from our list of trackers!";
return _("Non-i2p tracker in \"{0}\", deleting it from our list of trackers!", info.getName());
List files = info.getFiles();
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
return "Too many files in " + info.getName() + " (" + files.size() + "), deleting it!";
return _("Too many files in \"{0}\" ({1}), deleting it!", info.getName(), files.size());
} else if ( (files == null) && (info.getName().endsWith(".torrent")) ) {
return _("Torrent file \"{0}\" cannot end in \".torrent\", deleting it!", info.getName());
} else if (info.getPieces() <= 0) {
return "No pieces in " + info.getName() + "? deleting it!";
return _("No pieces in \"{0}\", deleting it!", info.getName());
} else if (info.getPieces() > Storage.MAX_PIECES) {
return _("Too many pieces in \"{0}\", limit is {1}, deleting it!", info.getName(), Storage.MAX_PIECES);
} else if (info.getPieceLength(0) > Storage.MAX_PIECE_SIZE) {
return "Pieces are too large in " + info.getName() + " (" + DataHelper.formatSize(info.getPieceLength(0)) +
"B), deleting it.";
return _("Pieces are too large in \"{0}\" ({1}B), deleting it.", info.getName(), DataHelper.formatSize(info.getPieceLength(0))) + ' ' +
_("Limit is {0}B", DataHelper.formatSize(Storage.MAX_PIECE_SIZE));
} else if (info.getTotalLength() > Storage.MAX_TOTAL_SIZE) {
System.out.println("torrent info: " + info.toString());
List lengths = info.getLengths();
@ -564,8 +576,7 @@ public class SnarkManager implements Snark.CompleteListener {
for (int i = 0; i < lengths.size(); i++)
System.out.println("File " + i + " is " + lengths.get(i) + " long.");
return "Torrents larger than " + DataHelper.formatSize(Storage.MAX_TOTAL_SIZE) +
"B are not supported yet (because we're paranoid): " + info.getName() + ", deleting it!";
return _("Torrents larger than {0}B are not supported yet, deleting \"{1}\"", Storage.MAX_TOTAL_SIZE, info.getName());
} else {
// ok
return null;
@ -581,7 +592,7 @@ public class SnarkManager implements Snark.CompleteListener {
filename = sfile.getCanonicalPath();
} catch (IOException ioe) {
_log.error("Unable to remove the torrent " + filename, ioe);
addMessage("ERR: Could not remove the torrent '" + filename + "': " + ioe.getMessage());
addMessage(_("Error: Could not remove the torrent {0}", filename) + ": " + ioe.getMessage());
return null;
}
int remaining = 0;
@ -602,7 +613,7 @@ public class SnarkManager implements Snark.CompleteListener {
////_util.
}
if (!wasStopped)
addMessage("Torrent stopped: '" + sfile.getName() + "'.");
addMessage(_("Torrent stopped: \"{0}\"", sfile.getName()));
}
return torrent;
}
@ -617,7 +628,7 @@ public class SnarkManager implements Snark.CompleteListener {
torrentFile.delete();
if (torrent.storage != null)
removeTorrentStatus(torrent.storage.getMetaInfo());
addMessage("Torrent removed: '" + torrentFile.getName() + "'.");
addMessage(_("Torrent removed: \"{0}\"", torrentFile.getName()));
}
}
@ -650,7 +661,7 @@ public class SnarkManager implements Snark.CompleteListener {
public void torrentComplete(Snark snark) {
File f = new File(snark.torrent);
long len = snark.meta.getTotalLength();
addMessage("Download finished: " + f.getName() + " (size: " + DataHelper.formatSize(len) + "B)");
addMessage(_("Download finished: \"{0}\"", f.getName()) + " (" + _("size: {0}B", DataHelper.formatSize(len)) + ')');
updateStatus(snark);
}
@ -678,7 +689,7 @@ public class SnarkManager implements Snark.CompleteListener {
// already known. noop
} else {
if (shouldAutoStart() && !_util.connect())
addMessage("Unable to connect to I2P!");
addMessage(_("Unable to connect to I2P!"));
addTorrent((String)foundNames.get(i), !shouldAutoStart());
}
}
@ -694,6 +705,24 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
/** translate */
private String _(String s) {
return _util.getString(s);
}
/** translate */
private String _(String s, Object o) {
return _util.getString(s, o);
}
/** translate */
private String _(String s, Object o, Object o2) {
return _util.getString(s, o, o2);
}
/**
* "name", "announceURL=websiteURL" pairs
*/
private static final String DEFAULT_TRACKERS[] = {
// "Postman", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php=http://tracker.postman.i2p/"
// , "eBook", "http://E71FRom6PZNEqTN2Lr8P-sr23b7HJVC32KoGnVQjaX6zJiXwhJy2HsXob36Qmj81TYFZdewFZa9mSJ533UZgGyQkXo2ahctg82JKYZfDe5uDxAn1E9YPjxZCWJaFJh0S~UwSs~9AZ7UcauSJIoNtpxrtbmRNVFLqnkEDdLZi26TeucfOmiFmIWnVblLniWv3tG1boE9Abd-6j3FmYVrRucYuepAILYt6katmVNOk6sXmno1Eynrp~~MBuFq0Ko6~jsc2E2CRVYXDhGHEMdt-j6JUz5D7S2RIVzDRqQyAZLKJ7OdQDmI31przzmne1vOqqqLC~1xUumZVIvF~yOeJUGNjJ1Vx0J8i2BQIusn1pQJ6UCB~ZtZZLQtEb8EPVCfpeRi2ri1M5CyOuxN0V5ekmPHrYIBNevuTCRC26NP7ZS5VDgx1~NaC3A-CzJAE6f1QXi0wMI9aywNG5KGzOPifcsih8eyGyytvgLtrZtV7ykzYpPCS-rDfITncpn5hliPUAAAA.i2p/pub/bt/announce.php=http://de-ebook-archiv.i2p/pub/bt/"
@ -705,9 +734,8 @@ public class SnarkManager implements Snark.CompleteListener {
// , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/"
// , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/"
"POSTMAN", "http://tracker2.postman.i2p/announce.php=http://tracker2.postman.i2p/"
,"WELTERDE", "http://BGKmlDOoH3RzFbPRfRpZV2FjpVj8~3moFftw5-dZfDf2070TOe8Tf2~DAVeaM6ZRLdmFEt~9wyFL8YMLMoLoiwGEH6IGW6rc45tstN68KsBDWZqkTohV1q9XFgK9JnCwE~Oi89xLBHsLMTHOabowWM6dkC8nI6QqJC2JODqLPIRfOVrDdkjLwtCrsckzLybNdFmgfoqF05UITDyczPsFVaHtpF1sRggOVmdvCM66otyonlzNcJbn59PA-R808vUrCPMGU~O9Wys0i-NoqtIbtWfOKnjCRFMNw5ex4n9m5Sxm9e20UkpKG6qzEuvKZWi8vTLe1NW~CBrj~vG7I3Ok4wybUFflBFOaBabxYJLlx4xTE1zJIVxlsekmAjckB4v-cQwulFeikR4LxPQ6mCQknW2HZ4JQIq6hL9AMabxjOlYnzh7kjOfRGkck8YgeozcyTvcDUcUsOuSTk06L4kdrv8h2Cozjbloi5zl6KTbj5ZTciKCxi73Pn9grICn-HQqEAAAA.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
,"WELTERDE", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
, "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
};
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */

View File

@ -57,7 +57,8 @@ public class Storage
/** The default piece size. */
private static final int MIN_PIECE_SIZE = 256*1024;
public static final int MAX_PIECE_SIZE = 1024*1024;
/** note that we start reducing max number of peer connections above 1MB */
public static final int MAX_PIECE_SIZE = 2*1024*1024;
/** The maximum number of pieces in a torrent. */
public static final int MAX_PIECES = 10*1024;
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;

View File

@ -315,7 +315,7 @@ public class TrackerClient extends I2PAppThread
// try to contact everybody we can
// Don't try to restart I2CP connection just to say goodbye
for (Iterator iter = trackers.iterator(); iter.hasNext(); ) {
if (!verifyConnected()) return;
if (!_util.connected()) return;
Tracker tr = (Tracker)iter.next();
if (tr.started && (!tr.stop) && tr.trackerProblems == null)
doRequest(tr, infoHash, peerID, uploaded,
@ -370,8 +370,13 @@ public class TrackerClient extends I2PAppThread
}
/**
* Very lazy byte[] to URL encoder. Just encodes everything, even
* "normal" chars.
* Very lazy byte[] to URL encoder. Just encodes almost everything, even
* some "normal" chars.
* By not encoding about 1/4 of the chars, we make random data like hashes about 16% smaller.
*
* RFC1738: 0-9a-zA-Z$-_.+!*'(),
* Us: 0-9a-zA-Z
*
*/
public static String urlencode(byte[] bs)
{
@ -379,10 +384,16 @@ public class TrackerClient extends I2PAppThread
for (int i = 0; i < bs.length; i++)
{
int c = bs[i] & 0xFF;
sb.append('%');
if (c < 16)
sb.append('0');
sb.append(Integer.toHexString(c));
if ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z')) {
sb.append((char)c);
} else {
sb.append('%');
if (c < 16)
sb.append('0');
sb.append(Integer.toHexString(c));
}
}
return sb.toString();

View File

@ -80,13 +80,25 @@ public class I2PSnarkServlet extends HttpServlet {
}
PrintWriter out = resp.getWriter();
out.write(HEADER_BEGIN);
out.write("<html>\n" +
"<head>\n" +
"<title>");
out.write(_("I2PSnark - Anonymous BitTorrent Client"));
out.write("</title>\n");
// we want it to go to the base URI so we don't refresh with some funky action= value
out.write("<meta http-equiv=\"refresh\" content=\"60;" + req.getRequestURI() + peerString + "\">\n");
out.write(HEADER);
out.write("</head><body>");
out.write("<center>");
out.write("<div class=\"snarknavbar\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\"Refresh page\" class=\"snarkRefresh\">I2PSnark</a> <a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\" target=\"_blank\">Forum</a>\n");
out.write("<div class=\"snarknavbar\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\"");
out.write(_("Refresh page"));
out.write("\" class=\"snarkRefresh\">");
out.write(_("I2PSnark"));
out.write("</a> <a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\" target=\"_blank\">");
out.write(_("Forum"));
out.write("</a>\n");
Map trackers = _manager.getTrackers();
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
@ -110,22 +122,51 @@ public class I2PSnarkServlet extends HttpServlet {
List snarks = getSortedSnarks(req);
String uri = req.getRequestURI();
out.write(TABLE_HEADER);
out.write(_("Status"));
if (_manager.util().connected() && snarks.size() > 0) {
if (peerParam != null)
out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br>\n");
else
out.write("(<a href=\"" + req.getRequestURI() + "?p=1" + "\">Show Peers</a>)<br>\n");
out.write(" (<a href=\"");
out.write(req.getRequestURI());
if (peerParam != null) {
out.write("\">");
out.write(_("Hide Peers"));
} else {
out.write("?p=1\">");
out.write(_("Show Peers"));
}
out.write("</a>)<br>\n");
}
out.write(TABLE_HEADER2);
out.write("</th>\n<th align=\"left\">");
out.write(_("Torrent"));
out.write("</th>\n<th align=\"center\">");
out.write(_("ETA"));
out.write("</th>\n<th align=\"right\">");
out.write(_("Downloaded"));
out.write("</th>\n<th align=\"right\">");
out.write(_("Uploaded"));
out.write("</th>\n<th align=\"right\">");
out.write(_("Down Rate"));
out.write("</th>\n<th align=\"right\">");
out.write(_("Up Rate"));
out.write("</th>\n");
out.write("<th align=\"center\">");
if (_manager.util().connected())
if (_manager.util().connected()) {
out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce +
"\" title=\"Stop all torrents and the I2P tunnel\">Stop All</a>");
else if (snarks.size() > 0)
"\" title=\"");
out.write(_("Stop all torrents and the I2P tunnel"));
out.write("\">");
out.write(_("Stop All"));
out.write("</a>");
} else if (snarks.size() > 0) {
out.write("<a href=\"" + uri + "?action=StartAll&nonce=" + _nonce +
"\" title=\"Start all torrents and the I2P tunnel\">Start All</a>");
else
"\" title=\"");
out.write(_("Start all torrents and the I2P tunnel"));
out.write("\">");
out.write(_("Start All"));
out.write("</a>");
} else {
out.write("&nbsp;");
}
out.write("</th></tr></thead>\n");
for (int i = 0; i < snarks.size(); i++) {
Snark snark = (Snark)snarks.get(i);
@ -133,14 +174,23 @@ public class I2PSnarkServlet extends HttpServlet {
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam);
displaySnark(out, snark, uri, i, stats, showPeers, showDebug);
}
if (snarks.size() <= 0) {
out.write(TABLE_EMPTY);
out.write("<tr class=\"snarkTorrentEven\">" +
"<td class=\"snarkTorrentEven\" align=\"center\"" +
" colspan=\"8\"><i>");
out.write(_("No torrents loaded."));
out.write("</i></td></tr>\n");
} else if (snarks.size() > 1) {
out.write("<tfoot><tr>\n" +
" <th align=\"left\" colspan=\"2\">Totals (" +
snarks.size() + " torrents, " +
DataHelper.formatSize(stats[5]) + "B, " +
stats[4] + " connected peers)</th>\n" +
" <th align=\"left\" colspan=\"2\">");
out.write(_("Totals"));
out.write(" (");
out.write(_("{0} torrents", snarks.size()));
out.write(", ");
out.write(DataHelper.formatSize(stats[5]) + "B, ");
out.write(_("{0} connected peers", stats[4]));
out.write(")</th>\n" +
" <th>&nbsp;</th>\n" +
" <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
" <th align=\"right\">" + formatSize(stats[1]) + "</th>\n" +
@ -166,7 +216,7 @@ public class I2PSnarkServlet extends HttpServlet {
String action = req.getParameter("action");
if (action == null) {
// noop
} else if ("Add torrent".equals(action)) {
} else if ("Add".equals(action)) {
String newFile = req.getParameter("newFile");
String newURL = req.getParameter("newURL");
// NOTE - newFile currently disabled in HTML form - see below
@ -174,7 +224,7 @@ public class I2PSnarkServlet extends HttpServlet {
if ( (newFile != null) && (newFile.trim().length() > 0) )
f = new File(newFile.trim());
if ( (f != null) && (!f.exists()) ) {
_manager.addMessage("Torrent file " + newFile +" does not exist");
_manager.addMessage(_("Torrent file {0} does not exist", newFile));
}
if ( (f != null) && (f.exists()) ) {
File local = new File(_manager.getDataDir(), f.getName());
@ -184,16 +234,16 @@ public class I2PSnarkServlet extends HttpServlet {
if (local.exists()) {
if (_manager.getTorrent(canonical) != null)
_manager.addMessage("Torrent already running: " + newFile);
_manager.addMessage(_("Torrent already running: {0}", newFile));
else
_manager.addMessage("Torrent already in the queue: " + newFile);
_manager.addMessage(_("Torrent already in the queue: {0}", newFile));
} else {
boolean ok = FileUtil.copy(f.getAbsolutePath(), local.getAbsolutePath(), true);
if (ok) {
_manager.addMessage("Copying torrent to " + local.getAbsolutePath());
_manager.addMessage(_("Copying torrent to {0}", local.getAbsolutePath()));
_manager.addTorrent(canonical);
} else {
_manager.addMessage("Unable to copy the torrent to " + local.getAbsolutePath() + " from " + f.getAbsolutePath());
_manager.addMessage(_("Unable to copy the torrent to {0}", local.getAbsolutePath()) + ' ' + _("from {0}", f.getAbsolutePath()));
}
}
} catch (IOException ioe) {
@ -201,11 +251,11 @@ public class I2PSnarkServlet extends HttpServlet {
}
} else if (newURL != null) {
if (newURL.startsWith("http://")) {
_manager.addMessage("Fetching " + newURL);
_manager.addMessage(_("Fetching {0}", newURL));
I2PAppThread fetch = new I2PAppThread(new FetchAndAdd(_manager, newURL), "Fetch and add");
fetch.start();
} else {
_manager.addMessage("Invalid URL - must start with http://");
_manager.addMessage(_("Invalid URL - must start with http://"));
}
} else {
// no file or URL specified
@ -235,7 +285,7 @@ public class I2PSnarkServlet extends HttpServlet {
Snark snark = _manager.getTorrent(name);
if ( (snark != null) && (DataHelper.eq(infoHash, snark.meta.getInfoHash())) ) {
snark.startTorrent();
_manager.addMessage("Starting up torrent " + name);
_manager.addMessage(_("Starting up torrent {0}", name));
break;
}
}
@ -255,7 +305,7 @@ public class I2PSnarkServlet extends HttpServlet {
// yeah, need to, otherwise it'll get autoadded again (at the moment
File f = new File(name);
f.delete();
_manager.addMessage("Torrent file deleted: " + f.getAbsolutePath());
_manager.addMessage(_("Torrent file deleted: {0}", f.getAbsolutePath()));
break;
}
}
@ -273,15 +323,15 @@ public class I2PSnarkServlet extends HttpServlet {
_manager.stopTorrent(name, true);
File f = new File(name);
f.delete();
_manager.addMessage("Torrent file deleted: " + f.getAbsolutePath());
_manager.addMessage(_("Torrent file deleted: {0}", f.getAbsolutePath()));
List files = snark.meta.getFiles();
String dataFile = snark.meta.getName();
f = new File(_manager.getDataDir(), dataFile);
if (files == null) { // single file torrent
if (f.delete())
_manager.addMessage("Data file deleted: " + f.getAbsolutePath());
_manager.addMessage(_("Data file deleted: {0}", f.getAbsolutePath()));
else
_manager.addMessage("Data file could not be deleted: " + f.getAbsolutePath());
_manager.addMessage(_("Data file could not be deleted: {0}", f.getAbsolutePath()));
break;
}
for (int i = 0; i < files.size(); i++) { // pass 1 delete files
@ -289,9 +339,9 @@ public class I2PSnarkServlet extends HttpServlet {
// each of those lists just contain a single file afaict...
File df = Storage.getFileFromNames(f, (List) files.get(i));
if (df.delete())
_manager.addMessage("Data file deleted: " + df.getAbsolutePath());
_manager.addMessage(_("Data file deleted: {0}", df.getAbsolutePath()));
else
_manager.addMessage("Data file could not be deleted: " + df.getAbsolutePath());
_manager.addMessage(_("Data file could not be deleted: {0}", df.getAbsolutePath()));
}
for (int i = files.size() - 1; i >= 0; i--) { // pass 2 delete dirs - not foolproof,
// we could sort and do a strict bottom-up
@ -300,14 +350,14 @@ public class I2PSnarkServlet extends HttpServlet {
if (df == null || !df.exists())
continue;
if(df.delete())
_manager.addMessage("Data dir deleted: " + df.getAbsolutePath());
_manager.addMessage(_("Data dir deleted: {0}", df.getAbsolutePath()));
}
break;
}
}
}
}
} else if ("Save configuration".equals(action)) {
} else if ("Save".equals(action)) {
String dataDir = req.getParameter("dataDir");
boolean autoStart = req.getParameter("autoStart") != null;
String seedPct = req.getParameter("seedPct");
@ -321,7 +371,7 @@ public class I2PSnarkServlet extends HttpServlet {
boolean useOpenTrackers = req.getParameter("useOpenTrackers") != null;
String openTrackers = req.getParameter("openTrackers");
_manager.updateConfig(dataDir, autoStart, seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts, upLimit, upBW, useOpenTrackers, openTrackers);
} else if ("Create torrent".equals(action)) {
} else if ("Create".equals(action)) {
String baseData = req.getParameter("baseFile");
if (baseData != null && baseData.trim().length() > 0) {
File baseFile = new File(_manager.getDataDir(), baseData);
@ -331,7 +381,7 @@ public class I2PSnarkServlet extends HttpServlet {
announceURL = announceURLOther;
if (announceURL == null || announceURL.length() <= 0)
_manager.addMessage("Error creating torrent - you must select a tracker");
_manager.addMessage(_("Error creating torrent - you must select a tracker"));
else if (baseFile.exists()) {
try {
Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
@ -346,21 +396,21 @@ public class I2PSnarkServlet extends HttpServlet {
FileOutputStream out = new FileOutputStream(torrentFile);
out.write(info.getTorrentData());
out.close();
_manager.addMessage("Torrent created for " + baseFile.getName() + ": " + torrentFile.getAbsolutePath());
_manager.addMessage(_("Torrent created for \"{0}\"", baseFile.getName()) + ": " + torrentFile.getAbsolutePath());
// now fire it up, but don't automatically seed it
_manager.addTorrent(torrentFile.getCanonicalPath(), true);
_manager.addMessage("Many I2P trackers require you to register new torrents before seeding - please do so before starting " + baseFile.getName());
_manager.addMessage(_("Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\"", baseFile.getName()));
} catch (IOException ioe) {
_manager.addMessage("Error creating a torrent for " + baseFile.getAbsolutePath() + ": " + ioe.getMessage());
_manager.addMessage(_("Error creating a torrent for \"{0}\"", baseFile.getAbsolutePath()) + ": " + ioe.getMessage());
}
} else {
_manager.addMessage("Cannot create a torrent for the nonexistent data: " + baseFile.getAbsolutePath());
_manager.addMessage(_("Cannot create a torrent for the nonexistent data: {0}", baseFile.getAbsolutePath()));
}
} else {
_manager.addMessage("Error creating torrent - you must enter a file or directory");
_manager.addMessage(_("Error creating torrent - you must enter a file or directory"));
}
} else if ("StopAll".equals(action)) {
_manager.addMessage("Stopping all torrents and closing the I2P tunnel.");
_manager.addMessage(_("Stopping all torrents and closing the I2P tunnel."));
List snarks = getSortedSnarks(req);
for (int i = 0; i < snarks.size(); i++) {
Snark snark = (Snark)snarks.get(i);
@ -369,10 +419,10 @@ public class I2PSnarkServlet extends HttpServlet {
}
if (_manager.util().connected()) {
_manager.util().disconnect();
_manager.addMessage("I2P tunnel closed.");
_manager.addMessage(_("I2P tunnel closed."));
}
} else if ("StartAll".equals(action)) {
_manager.addMessage("Opening the I2P tunnel and starting all torrents.");
_manager.addMessage(_("Opening the I2P tunnel and starting all torrents."));
List snarks = getSortedSnarks(req);
for (int i = 0; i < snarks.size(); i++) {
Snark snark = (Snark)snarks.get(i);
@ -449,45 +499,45 @@ public class I2PSnarkServlet extends HttpServlet {
knownPeers = snark.coordinator.trackerSeenPeers;
}
String statusString = "Unknown";
String statusString = _("Unknown");
if (err != null) {
if (isRunning && curPeers > 0 && !showPeers)
statusString = "<a title=\"" + err + "\">TrackerErr</a> (" +
statusString = "<a title=\"" + err + "\">" + _("TrackerErr") + "</a> (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + _("peers") + "</a>)";
else if (isRunning)
statusString = "<a title=\"" + err + "\">TrackerErr (" + curPeers + "/" + knownPeers + " peers)";
statusString = "<a title=\"" + err + "\">" + _("TrackerErr") + " (" + curPeers + '/' + knownPeers + ' ' + _("peers") + ')';
else {
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "&hellip;";
statusString = "TrackerErr<br>(" + err + ")";
statusString = _("TrackerErr") + "<br>(" + err + ")";
}
} else if (remaining <= 0) {
if (isRunning && curPeers > 0 && !showPeers)
statusString = "Seeding (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
statusString = _("Seeding") + " (" +
curPeers + '/' + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + _("peers") + "</a>)";
else if (isRunning)
statusString = "Seeding (" + curPeers + "/" + knownPeers + " peers)";
statusString = _("Seeding") + " (" + curPeers + "/" + knownPeers + ' ' + _("peers") + ')';
else
statusString = "Complete";
statusString = _("Complete");
} else {
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
statusString = "OK (" +
statusString = _("OK") + " (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + _("peers") + "</a>)";
else if (isRunning && curPeers > 0 && downBps > 0)
statusString = "OK (" + curPeers + "/" + knownPeers + " peers)";
statusString = _("OK") + " (" + curPeers + "/" + knownPeers + ' ' + _("peers") + ')';
else if (isRunning && curPeers > 0 && !showPeers)
statusString = "Stalled (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
statusString = _("Stalled") + " (" +
curPeers + '/' + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + _("peers") + "</a>)";
else if (isRunning && curPeers > 0)
statusString = "Stalled (" + curPeers + "/" + knownPeers + " peers)";
statusString = _("Stalled") + " (" + curPeers + '/' + knownPeers + ' ' + _("peers") + ')';
else if (isRunning)
statusString = "No Peers (0/" + knownPeers + ")";
statusString = _("No Peers") + " (0/" + knownPeers + ')';
else
statusString = "Stopped";
statusString = _("Stopped");
}
String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
@ -496,9 +546,15 @@ public class I2PSnarkServlet extends HttpServlet {
out.write(statusString + "</td>\n\t");
out.write("<td align=\"left\" class=\"snarkTorrentName " + rowClass + "\">");
if (remaining == 0)
if (remaining == 0) {
out.write("<a href=\"" + _manager.linkPrefix() + snark.meta.getName()
+ "\" title=\"View file\">");
+ "\" title=\"");
if (snark.meta.getFiles() != null)
out.write(_("View files"));
else
out.write(_("Open file"));
out.write("\">");
}
out.write(filename);
if (remaining == 0)
out.write("</a>");
@ -520,7 +576,9 @@ public class I2PSnarkServlet extends HttpServlet {
baseURL = baseURL.substring(e + 1);
out.write("&nbsp;&nbsp;&nbsp;[<a href=\"" + baseURL + "details.php?dllist=1&filelist=1&info_hash=");
out.write(TrackerClient.urlencode(snark.meta.getInfoHash()));
out.write("\" title=\"" + name + " Tracker\">Details</a>]");
out.write("\" title=\"" + name + ' ' + _("Tracker") + "\">");
out.write(_("Details"));
out.write("</a>]");
break;
}
}
@ -552,17 +610,35 @@ public class I2PSnarkServlet extends HttpServlet {
parameters = parameters + "&p=1";
if (isRunning) {
out.write("<a href=\"" + uri + "?action=Stop" + parameters
+ "\" title=\"Stop the torrent\">Stop</a>");
+ "\" title=\"");
out.write(_("Stop the torrent"));
out.write("\">");
out.write(_("Stop"));
out.write("</a>");
} else {
if (isValid)
if (isValid) {
out.write("<a href=\"" + uri + "?action=Start" + parameters
+ "\" title=\"Start the torrent\">Start</a> ");
+ "\" title=\"");
out.write(_("Start the torrent"));
out.write("\">");
out.write(_("Start"));
out.write("</a>\n");
}
out.write("<a href=\"" + uri + "?action=Remove" + parameters
+ "\" title=\"Remove the torrent from the active list, deleting the .torrent file\">Remove</a><br>");
+ "\" title=\"");
out.write(_("Remove the torrent from the active list, deleting the .torrent file"));
out.write("\">");
out.write(_("Remove"));
out.write("</a><br>");
out.write("<a href=\"" + uri + "?action=Delete" + parameters
+ "\" title=\"Delete the .torrent file and the associated data file(s)\">Delete</a> ");
+ "\" title=\"");
out.write(_("Delete the .torrent file and the associated data file(s)"));
out.write("\">");
out.write(_("Delete"));
out.write("</a>");
}
out.write("</td>\n</tr>\n");
if(showPeers && isRunning && curPeers > 0) {
List peers = snark.coordinator.peerList();
Iterator it = peers.iterator();
@ -573,11 +649,11 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<tr class=\"" + rowClass + "\">");
out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("</td>\n\t");
out.write("<td align=\"left\" class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
String ch = peer.toString().substring(0, 4);
String client;
if ("AwMD".equals(ch))
client = "I2PSnark";
client = _("I2PSnark");
else if ("BFJT".equals(ch))
client = "I2PRufus";
else if ("TTMt".equals(ch))
@ -586,12 +662,12 @@ public class I2PSnarkServlet extends HttpServlet {
client = "Azureus";
else if ("CwsL".equals(ch))
client = "I2PSnarkXL";
else if ("ZV".equals(ch.substring(2,4)))
client = "Robert";
else if ("VUZP".equals(ch))
else if ("ZV".equals(ch.substring(2,4)) || "VUZP".equals(ch))
client = "Robert";
else if (ch.startsWith("LV")) // LVCS 1.0.2?; LVRS 1.0.4
client = "Transmission";
else
client = "Unknown (" + ch + ')';
client = _("Unknown") + " (" + ch + ')';
out.write(client + "&nbsp;&nbsp;" + peer.toString().substring(5, 9));
if (showDebug)
out.write(" inactive " + (peer.getInactiveTime() / 1000) + "s");
@ -601,7 +677,7 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
float pct = (float) (100.0 * (float) peer.completed() / snark.meta.getPieces());
if (pct == 100.0)
out.write("Seed");
out.write(_("Seed"));
else {
String ps = String.valueOf(pct);
if (ps.length() > 5)
@ -619,9 +695,10 @@ public class I2PSnarkServlet extends HttpServlet {
} else {
out.write("<font color=#a00000><a title=\"");
if (!peer.isInteresting())
out.write("Uninteresting\">");
out.write(_("Uninteresting (The peer has no pieces we need)"));
else
out.write("Choked\">");
out.write(_("Choked (The peer is not allowing us to request pieces)"));
out.write("\">");
out.write(formatSize(peer.getDownloadRate()) + "ps</a></font>");
}
}
@ -634,9 +711,10 @@ public class I2PSnarkServlet extends HttpServlet {
} else {
out.write("<font color=#a00000><a title=\"");
if (!peer.isInterested())
out.write("Uninterested\">");
out.write(_("Uninterested (We have no pieces the peer needs)"));
else
out.write("Choking\">");
out.write(_("Choking (We are not allowing the peer to request pieces)"));
out.write("\">");
out.write(formatSize(peer.getUploadRate()) + "ps</a></font>");
}
}
@ -659,14 +737,23 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<span class=\"snarkNewTorrent\">\n");
// *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" />\n");
out.write("<div class=\"addtorrentsection\"><span class=\"snarkConfigTitle\">Add Torrent:</span><br>\n");
out.write("From URL&nbsp;: <input type=\"text\" name=\"newURL\" size=\"80\" value=\"" + newURL + "\" /> \n");
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
out.write("<input type=\"hidden\" name=\"action\" value=\"Add\" >\n");
out.write("<div class=\"addtorrentsection\"><span class=\"snarkConfigTitle\">");
out.write(_("Add Torrent"));
out.write("</span><br>\n<table border=\"0\"><tr><td>");
out.write(_("From URL"));
out.write(":<td><input type=\"text\" name=\"newURL\" size=\"80\" value=\"" + newURL + "\" > \n");
// not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
out.write("<input type=\"submit\" value=\"Add torrent\" name=\"action\" /><br>\n");
out.write("<span class=\"snarkAddInfo\">Alternately, you can copy .torrent files to " + _manager.getDataDir().getAbsolutePath() + "<br>\n");
out.write("Removing that .torrent file will cause the torrent to stop.<br></span>\n");
out.write("<tr><td>&nbsp;<td><input type=\"submit\" value=\"");
out.write(_("Add torrent"));
out.write("\" name=\"foo\" ><br>\n");
out.write("<tr><td>&nbsp;<td><span class=\"snarkAddInfo\">");
out.write(_("Alternately, you can copy .torrent files to the directory {0}.", _manager.getDataDir().getAbsolutePath()));
out.write("\n");
out.write(_("Removing a .torrent file will cause the torrent to stop."));
out.write("<br></span></table>\n");
out.write("</form>\n</span></div>");
}
@ -679,13 +766,22 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<div class=\"newtorrentsection\"><span class=\"snarkNewTorrent\">\n");
// *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" />\n");
out.write("<span class=\"snarkConfigTitle\">Create Torrent:</span><br>\n");
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
out.write("<input type=\"hidden\" name=\"action\" value=\"Create\" >\n");
out.write("<span class=\"snarkConfigTitle\">");
out.write(_("Create Torrent"));
out.write("</span><br>\n<table border=\"0\"><tr><td>");
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
out.write("Data to seed: " + _manager.getDataDir().getAbsolutePath() + File.separatorChar
out.write(_("Data to seed"));
out.write(":<td>" + _manager.getDataDir().getAbsolutePath() + File.separatorChar
+ "<input type=\"text\" name=\"baseFile\" size=\"20\" value=\"" + baseFile
+ "\" title=\"File to seed (must be within the specified path)\" /><br>\n");
out.write("Tracker: <select name=\"announceURL\"><option value=\"\">Select a tracker</option>\n");
+ "\" title=\"");
out.write(_("File or directory to seed (must be within the specified path)"));
out.write("\" ><tr><td>\n");
out.write(_("Tracker"));
out.write(":<td><select name=\"announceURL\"><option value=\"\">");
out.write(_("Select a tracker"));
out.write("</option>\n");
Map trackers = _manager.getTrackers();
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
@ -697,9 +793,14 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("\t<option value=\"" + announceURL + "\">" + name + "</option>\n");
}
out.write("</select>\n");
out.write("or <input type=\"text\" name=\"announceURLOther\" size=\"50\" value=\"http://\" " +
"title=\"Custom tracker URL\" /> ");
out.write("<input type=\"submit\" value=\"Create torrent\" name=\"action\" />\n");
out.write(_("or"));
out.write("<tr><td>&nbsp;<td><input type=\"text\" name=\"announceURLOther\" size=\"50\" value=\"http://\" " +
"title=\"");
out.write(_("Specify custom tracker announce URL"));
out.write("\" > ");
out.write("<tr><td>&nbsp;<td><input type=\"submit\" value=\"");
out.write(_("Create torrent"));
out.write("\" name=\"foo\" ></table>\n");
out.write("</form>\n</span></div>");
}
@ -713,13 +814,28 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n");
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" />\n");
out.write("<span class=\"snarkConfigTitle\">Configuration:</span><br>\n");
out.write("Data directory: <input type=\"text\" size=\"40\" name=\"dataDir\" value=\"" + dataDir + "\" ");
out.write("title=\"Directory to store torrents and data\" disabled=\"true\" /> <i>(Edit i2psnark.config and restart to change)</i><br>\n");
out.write("Auto start: <input type=\"checkbox\" class=\"optbox\" name=\"autoStart\" value=\"true\" "
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
out.write("<input type=\"hidden\" name=\"action\" value=\"Save\" >\n");
out.write("<span class=\"snarkConfigTitle\">");
out.write(_("Configuration"));
out.write("</span><br>\n");
out.write("<table border=\"0\"><tr><td>");
out.write(_("Data directory"));
out.write(": <td><input type=\"text\" size=\"50\" name=\"dataDir\" value=\"" + dataDir + "\" ");
out.write("title=\"");
out.write(_("Directory to store torrents and data"));
out.write("\" disabled=\"true\" ><br><i>(");
out.write(_("Edit i2psnark.config and restart to change"));
out.write(")</i><br>\n");
out.write("<tr><td>");
out.write(_("Auto start"));
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"autoStart\" value=\"true\" "
+ (autoStart ? "checked " : "")
+ "title=\"If true, automatically start torrents that are added\" />");
+ "title=\"");
out.write(_("If checked, automatically start torrents that are added"));
out.write("\" >");
//Auto add: <input type="checkbox" name="autoAdd" value="true" title="If true, automatically add torrents that are found in the data directory" />
//Auto stop: <input type="checkbox" name="autoStop" value="true" title="If true, automatically stop torrents that are removed from the data directory" />
//out.write("<br>\n");
@ -739,26 +855,51 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<option value=\"150\">150%</option>\n\t");
out.write("</select><br>\n");
*/
out.write("Total uploader limit: <input type=\"text\" name=\"upLimit\" value=\""
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" /> peers<br>\n");
out.write("Up bandwidth limit: <input type=\"text\" name=\"upBW\" value=\""
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" /> KBps <i>(Half <a href=\"/config.jsp\" target=\"blank\">available bandwidth</a> recommended.)</i><br>\n");
out.write("<tr><td>");
out.write(_("Total uploader limit"));
out.write(": <td><input type=\"text\" name=\"upLimit\" value=\""
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" > ");
out.write(_("peers"));
out.write("<br>\n");
out.write("<tr><td>");
out.write(_("Up bandwidth limit"));
out.write(": <td><input type=\"text\" name=\"upBW\" value=\""
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" > KBps <i>(");
out.write(_("Half available bandwidth recommended."));
out.write(" <a href=\"/config.jsp\" target=\"blank\">");
out.write(_("View or change router bandwidth"));
out.write("</a>)</i><br>\n");
out.write("Use open trackers also: <input type=\"checkbox\" class=\"optbox\" name=\"useOpenTrackers\" value=\"true\" "
out.write("<tr><td>");
out.write(_("Use open trackers also"));
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"useOpenTrackers\" value=\"true\" "
+ (useOpenTrackers ? "checked " : "")
+ "title=\"If true, uses open trackers in addition\" /> ");
out.write("Announce URLs: <input type=\"text\" name=\"openTrackers\" value=\""
+ openTrackers + "\" size=\"50\" /><br>\n");
+ "title=\"");
out.write(_("If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"));
out.write("\" > ");
out.write("<tr><td>");
out.write(_("Open tracker announce URLs"));
out.write(": <td><input type=\"text\" name=\"openTrackers\" value=\""
+ openTrackers + "\" size=\"50\" ><br>\n");
//out.write("\n");
//out.write("EepProxy host: <input type=\"text\" name=\"eepHost\" value=\""
// + _manager.util().getEepProxyHost() + "\" size=\"15\" /> ");
//out.write("port: <input type=\"text\" name=\"eepPort\" value=\""
// + _manager.util().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br>\n");
out.write("I2CP host: <input type=\"text\" name=\"i2cpHost\" value=\""
+ _manager.util().getI2CPHost() + "\" size=\"15\" /> ");
out.write("port: <input type=\"text\" name=\"i2cpPort\" value=\"" +
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" /> <br>\n");
out.write("<tr><td>");
out.write(_("I2CP host"));
out.write(": <td><input type=\"text\" name=\"i2cpHost\" value=\""
+ _manager.util().getI2CPHost() + "\" size=\"15\" > ");
out.write("<tr><td>");
out.write(_("I2CP port"));
out.write(": <td><input type=\"text\" name=\"i2cpPort\" value=\"" +
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" > <br>\n");
StringBuilder opts = new StringBuilder(64);
Map options = new TreeMap(_manager.util().getI2CPOptions());
for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) {
@ -767,13 +908,28 @@ public class I2PSnarkServlet extends HttpServlet {
String val = (String)entry.getValue();
opts.append(key).append('=').append(val).append(' ');
}
out.write("I2CP opts: <input type=\"text\" name=\"i2cpOpts\" size=\"80\" value=\""
+ opts.toString() + "\" /><br>\n");
out.write("<input type=\"submit\" value=\"Save configuration\" name=\"action\" />\n");
out.write("</span>\n");
out.write("<tr><td>");
out.write(_("I2CP options"));
out.write(": <td><textarea name=\"i2cpOpts\" cols=\"60\" rows=\"1\" wrap=\"off\" >"
+ opts.toString() + "</textarea><br>\n");
out.write("<tr><td>&nbsp;<td><input type=\"submit\" value=\"");
out.write(_("Save configuration"));
out.write("\" name=\"foo\" >\n");
out.write("</table></span>\n");
out.write("</form></div>");
}
/** translate */
private String _(String s) {
return _manager.util().getString(s);
}
/** translate */
private String _(String s, Object o) {
return _manager.util().getString(s, o);
}
// rounding makes us look faster :)
private String formatSize(long bytes) {
if (bytes < 5*1024)
@ -786,28 +942,12 @@ public class I2PSnarkServlet extends HttpServlet {
return ((bytes + 512*1024*1024)/(1024*1024*1024)) + "GB";
}
private static final String HEADER_BEGIN = "<html>\n" +
"<head>\n" +
"<title>I2PSnark - Anonymous BitTorrent Client</title>\n";
private static final String HEADER = "<link href=\"../themes/console/snark.css\" rel=\"stylesheet\" type=\"text/css\" />";
private static final String HEADER = "<link href=\"../themes/console/snark.css\" rel=\"stylesheet\" type=\"text/css\" >";
private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\" cellpadding=\"0 10px\">\n" +
"<thead>\n" +
"<tr><th align=\"center\">Status \n";
private static final String TABLE_HEADER2 = "</th>\n" +
" <th align=\"left\">Torrent</th>\n" +
" <th align=\"center\">ETA</th>\n" +
" <th align=\"right\">Downloaded</th>\n" +
" <th align=\"right\">Uploaded</th>\n" +
" <th align=\"right\">Down Rate</th>\n" +
" <th align=\"right\">Up Rate</th>\n";
private static final String TABLE_EMPTY = "<tr class=\"snarkTorrentEven\">" +
"<td class=\"snarkTorrentEven\" align=\"center\"" +
" colspan=\"8\"><i>No torrents loaded.</i></td></tr>\n";
"<tr><th align=\"center\">";
private static final String TABLE_FOOTER = "</table></div>\n";
@ -827,12 +967,13 @@ private static class FetchAndAdd implements Runnable {
File file = _manager.util().get(_url, false, 3);
try {
if ( (file != null) && (file.exists()) && (file.length() > 0) ) {
_manager.addMessage("Torrent fetched from " + _url);
_manager.addMessage(_("Torrent fetched from {0}", _url));
FileInputStream in = null;
try {
in = new FileInputStream(file);
MetaInfo info = new MetaInfo(in);
String name = info.getName();
name = DataHelper.stripHTML(name); // XSS
name = name.replace('/', '_');
name = name.replace('\\', '_');
name = name.replace('&', '+');
@ -846,25 +987,30 @@ private static class FetchAndAdd implements Runnable {
if (torrentFile.exists()) {
if (_manager.getTorrent(canonical) != null)
_manager.addMessage("Torrent already running: " + name);
_manager.addMessage(_("Torrent already running: {0}", name));
else
_manager.addMessage("Torrent already in the queue: " + name);
_manager.addMessage(_("Torrent already in the queue: {0}", name));
} else {
FileUtil.copy(file.getAbsolutePath(), canonical, true);
_manager.addTorrent(canonical);
}
} catch (IOException ioe) {
_manager.addMessage("Torrent at " + _url + " was not valid: " + ioe.getMessage());
_manager.addMessage(_("Torrent at {0} was not valid", _url) + ": " + ioe.getMessage());
} finally {
try { in.close(); } catch (IOException ioe) {}
}
} else {
_manager.addMessage("Torrent was not retrieved from " + _url);
_manager.addMessage(_("Torrent was not retrieved from {0}", _url));
}
} finally {
if (file != null) file.delete();
}
}
private String _(String s, String o) {
return _manager.util().getString(s, o);
}
}
}

View File

@ -58,6 +58,23 @@
<Arg>webapps/i2psnark.war</Arg>
</Call>
<!-- this is so we can find the css -->
<Call name="addContext">
<Arg>
<New class="org.mortbay.http.HttpContext">
<Set name="contextPath">/themes</Set>
<Set name="resourceBase">./docs/themes</Set>
<Call name="addHandler">
<Arg>
<New class="org.mortbay.http.handler.ResourceHandler">
<Set name="redirectWelcome">FALSE</Set>
</New>
</Arg>
</Call>
</New>
</Arg>
</Call>
<!-- =============================================================== -->
<!-- Configure the Other Server Options -->
<!-- =============================================================== -->

View File

@ -0,0 +1,655 @@
# 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: 2009-12-10 17:41+0000\n"
"PO-Revision-Date: 2009-10-19 12:50+0000\n"
"Last-Translator: foo <foo@bar>\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/org/klomp/snark/SnarkManager.java:84
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:241
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:243
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:255
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:257
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:301
msgid "Cannot change the I2CP settings while torrents are active"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:307
msgid "Disconnecting old I2CP destination"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:311
#, java-format
msgid "I2CP settings changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:315
msgid ""
"Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:319
msgid "Unable to reconnect with the old settings!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:321
msgid "Reconnected on the new I2CP destination"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:332
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:343
msgid "Enabled autostart"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:345
msgid "Disabled autostart"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:351
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:353
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:360
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:367
msgid "Configuration unchanged."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:377
#, java-format
msgid "Unable to save the config to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:395
msgid "Connecting to I2P"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:398
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:407
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:446
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:461
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:463
#, java-format
msgid "Torrent added: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:559
#, java-format
msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:562
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:564
#, java-format
msgid "Torrent file \"{0}\" cannot end in '.torrent', deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:566
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:568
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:570
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:571
#, java-format
msgid "Limit is {0}B"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:579
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:595
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:616
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:631
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:664
#, java-format
msgid "Download finished: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:664
#, java-format
msgid "size: {0}B"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:692
msgid "Unable to connect to I2P!"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:86
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:95
msgid "Refresh page"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:97
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:655
msgid "I2PSnark"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:99
msgid "Forum"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:125
msgid "Status"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:132
msgid "Hide Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:134
msgid "Show Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:138
msgid "Torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:140
msgid "ETA"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:142
msgid "Downloaded"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:144
msgid "Uploaded"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:146
msgid "Down Rate"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:148
msgid "Up Rate"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:155
msgid "Stop all torrents and the I2P tunnel"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:157
msgid "Stop All"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:162
msgid "Start all torrents and the I2P tunnel"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:164
msgid "Start All"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:181
msgid "No torrents loaded."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:186
msgid "Totals"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:188
#, java-format
msgid "{0} torrents"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:191
#, java-format
msgid "{0} connected peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:218
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:748
msgid "Add torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:226
#, java-format
msgid "Torrent file {0} does not exist"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:236
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:985
#, java-format
msgid "Torrent already running: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:238
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:242
#, java-format
msgid "Copying torrent to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:245
#, java-format
msgid "Unable to copy the torrent to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:245
#, java-format
msgid "from {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:253
#, java-format
msgid "Fetching {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:257
msgid "Invalid URL - must start with http://"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:262
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615
msgid "Stop"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:623
msgid "Start"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287
#, java-format
msgid "Starting up torrent {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:307
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:325
#, java-format
msgid "Torrent file deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:331
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:341
#, java-format
msgid "Data file deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:333
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352
#, java-format
msgid "Data dir deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:359
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:913
msgid "Save configuration"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:373
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:799
msgid "Create torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:383
msgid "Error creating torrent - you must select a tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398
#, java-format
msgid "Torrent created for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:401
#, java-format
msgid ""
"Many I2P trackers require you to register new torrents before seeding - "
"please do so before starting \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:403
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:406
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:409
msgid "Error creating torrent - you must enter a file or directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:412
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:421
msgid "I2P tunnel closed."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:424
msgid "Opening the I2P tunnel and starting all torrents."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:669
msgid "Unknown"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:504
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:512
msgid "TrackerErr"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:506
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:518
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:527
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:533
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:858
msgid "peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:516
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:520
msgid "Seeding"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522
msgid "Complete"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:525
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529
msgid "OK"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:535
msgid "Stalled"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537
msgid "No Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539
msgid "Stopped"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:552
msgid "View files"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554
msgid "Open file"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:578
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:778
msgid "Tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:579
msgid "Details"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:613
msgid "Stop the torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:621
msgid "Start the torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:628
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:630
msgid "Remove"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:634
msgid "Delete the .torrent file and the associated data file(s)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:636
msgid "Delete"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:679
msgid "Seed"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697
msgid "Uninteresting"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:699
msgid "Choked"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:713
msgid "Uninterested"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:715
msgid "Choking"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:741
msgid "Add Torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:743
msgid "From URL"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:751
#, java-format
msgid "Alternately, you can copy .torrent files to {0} ."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:753
msgid "Removing a .torrent file will cause the torrent to stop."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:769
msgid "Create Torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:772
msgid "Data to seed"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:776
msgid "File to seed (must be within the specified path)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:780
msgid "Select a tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793
msgid "or"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
msgid "Custom tracker URL"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:816
msgid "Configuration"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:819
msgid "Data directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:822
msgid "Directory to store torrents and data"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:824
msgid "Edit i2psnark.config and restart to change"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828
msgid "Auto start"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:832
msgid "If checked, automatically start torrents that are added"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:855
msgid "Total uploader limit"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:862
msgid "Up bandwidth limit"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:865
msgid "Half available bandwidth< recommended."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:867
msgid "Configure"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:871
msgid "Use open trackers also"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:875
msgid ""
"If checked, announce torrents to open trackers as well as the tracker listed "
"in the torrent file"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:879
msgid "Open tracker announce URLs"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:890
msgid "I2CP host"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:895
msgid "I2CP port"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:908
msgid "I2CP options"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966
#, java-format
msgid "Torrent fetched from {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993
#, java-format
msgid "Torrent at {0} was not valid"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:998
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr ""

View File

@ -0,0 +1,648 @@
# 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-01-14 06:24+0000\n"
"PO-Revision-Date: 2010-01-14 06:33+0000\n"
"Last-Translator: 4get <forget@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: Russian\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:84
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "Торренты будут подгружены через {0} минут(ы)"
#: ../java/src/org/klomp/snark/SnarkManager.java:241
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Новое значение лимита количества слотов отдачи: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:243
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "Минимально допустимое значение для количества слотов: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:255
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Новое значение лимита скорости отдачи: {0} KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:257
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "Минимально допустимое значение для лимита скорости отдачи: {0} KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:301
msgid "Cannot change the I2CP settings while torrents are active"
msgstr "Невозможно изменить настройки I2CP пока есть активные торренты"
#: ../java/src/org/klomp/snark/SnarkManager.java:307
msgid "Disconnecting old I2CP destination"
msgstr "Рассоединяемся по старому адресу I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:311
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "Новые параметры I2CP: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:315
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "Не удалось соединиться с использованием новых настроек I2CP, возвращаемся к старым настройкам"
#: ../java/src/org/klomp/snark/SnarkManager.java:319
msgid "Unable to reconnect with the old settings!"
msgstr "Не удалось пересоединиться с использованием старых настроек I2CP!"
#: ../java/src/org/klomp/snark/SnarkManager.java:321
msgid "Reconnected on the new I2CP destination"
msgstr "Пересоединились по новому адресу I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:332
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "I2CP-приёмник перезапущен для \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:343
msgid "Enabled autostart"
msgstr "Автостарт включен"
#: ../java/src/org/klomp/snark/SnarkManager.java:345
msgid "Disabled autostart"
msgstr "Автостарт выключен"
#: ../java/src/org/klomp/snark/SnarkManager.java:351
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "Включено использование открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу."
#: ../java/src/org/klomp/snark/SnarkManager.java:353
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "Отключено использование открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу."
#: ../java/src/org/klomp/snark/SnarkManager.java:360
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "Изменен список открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу."
#: ../java/src/org/klomp/snark/SnarkManager.java:367
msgid "Configuration unchanged."
msgstr "Настройки не изменились."
#: ../java/src/org/klomp/snark/SnarkManager.java:377
#, java-format
msgid "Unable to save the config to {0}"
msgstr "Не удалось сохранить настройки в {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:395
msgid "Connecting to I2P"
msgstr "Устанавливается соединение с I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:398
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Ошибка соединения с I2P, проверьте настройки I2CP!"
#: ../java/src/org/klomp/snark/SnarkManager.java:407
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Ошибка: Не удалось добавить торрент {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:446
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "Торрент в \"{0}\" некорректен"
#: ../java/src/org/klomp/snark/SnarkManager.java:461
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Торрент добавлен и запущен: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:463
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Торрент добавлен: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:559
#, java-format
msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
msgstr "Обнаружен не-I2P трекер в торренте \"{0}\", удаляем его из нашего списка трекеров!"
#: ../java/src/org/klomp/snark/SnarkManager.java:562
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "Слишком много файлов в торренте \"{0}\" ({1}), удаляем его!"
#: ../java/src/org/klomp/snark/SnarkManager.java:564
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "Торрент \"{0}\" содержит единственный файл заканчивающийся на \".torrent\", удаляем его!"
#: ../java/src/org/klomp/snark/SnarkManager.java:566
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "В торренте \"{0}\" не оказалось ни одной части, удаляем его!"
#: ../java/src/org/klomp/snark/SnarkManager.java:568
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "Слишком много частей в торренте \"{0}\" (наш предел {1}), удаляем его!"
#: ../java/src/org/klomp/snark/SnarkManager.java:570
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "Слишком крупные части в торренте \"{0}\" ({1}B), удаляем его."
#: ../java/src/org/klomp/snark/SnarkManager.java:571
#, java-format
msgid "Limit is {0}B"
msgstr "Наш предел {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:579
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Торренты крупнее чем {0}B пока не поддерживается, удаляем \"{1}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:595
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Ошибка: Невозможно удалить торрент {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:616
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Торрент остановлен: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:631
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Торрент удален: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:664
#, java-format
msgid "Download finished: \"{0}\""
msgstr "Завершена загрузка: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:664
#, java-format
msgid "size: {0}B"
msgstr "размер: {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:692
msgid "Unable to connect to I2P!"
msgstr "Не удалось установить соединение с I2P!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:86
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark — Анонимный BitTorrent Клиент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:95
msgid "Refresh page"
msgstr "Обновить страницу"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:97
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:656
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:99
msgid "Forum"
msgstr "Форум"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:125
msgid "Status"
msgstr "Статус"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:131
msgid "Hide Peers"
msgstr "спрятать список пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:134
msgid "Show Peers"
msgstr "показать список пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:139
msgid "Torrent"
msgstr "Торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:141
msgid "ETA"
msgstr "Осталось"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:143
msgid "Downloaded"
msgstr "Получено"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:145
msgid "Uploaded"
msgstr "Отдано"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:147
msgid "Down Rate"
msgstr "Скорость загрузки"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:149
msgid "Up Rate"
msgstr "Скорость отдачи"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:156
msgid "Stop all torrents and the I2P tunnel"
msgstr "Остановить все торренты и закрыть соединение с I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:158
msgid "Stop All"
msgstr "Остановить все"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:163
msgid "Start all torrents and the I2P tunnel"
msgstr "Запустить все торренты и открыть соединение с I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:165
msgid "Start All"
msgstr "Запустить все"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:182
msgid "No torrents loaded."
msgstr "Нет загруженных торрентов."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:187
msgid "Totals"
msgstr "Всего"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:189
#, java-format
msgid "{0} torrents"
msgstr "{0} торрентов"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:192
#, java-format
msgid "{0} connected peers"
msgstr "{0} подсоединенных пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:227
#, java-format
msgid "Torrent file {0} does not exist"
msgstr "Торрент {0} не существует"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:237
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:990
#, java-format
msgid "Torrent already running: {0}"
msgstr "Торрент уже запущен: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:239
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:992
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Торрент уже в очереди: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:243
#, java-format
msgid "Copying torrent to {0}"
msgstr "Копируем торрент в: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:246
#, java-format
msgid "Unable to copy the torrent to {0}"
msgstr "Не удалось скопировать торрент в: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:246
#, java-format
msgid "from {0}"
msgstr "из: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254
#, java-format
msgid "Fetching {0}"
msgstr "Получение торрента: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:258
msgid "Invalid URL - must start with http://"
msgstr "Некорректный URL, должен начинаться с http://"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288
#, java-format
msgid "Starting up torrent {0}"
msgstr "Запускаем торрент: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:326
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Удален торрент: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:332
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
#, java-format
msgid "Data file deleted: {0}"
msgstr "Файл удален: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:334
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:344
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Не удалось удалить файл: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Директория удалена: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:384
msgid "Error creating torrent - you must select a tracker"
msgstr "Торрент не создан — вы должны указать трекер"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:399
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Создан торрент для \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:402
#, java-format
msgid "Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\""
msgstr "Многие I2P трекеры требуют зарегистрировать на них торрент перед началом раздачи — пожалуйста проверьте требуется ли это перед запуском \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:404
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Ошибка при создании торрента для: \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Невозможно создать торрент для несуществующего файла или директории: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:410
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Торрент не создан — вы должны указать файл или директорию"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Останавливаем все торренты и закрываем соединение с I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:422
msgid "I2P tunnel closed."
msgstr "Соединение с I2P закрыто."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Соединяемся с I2P и запускаем все торренты."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:502
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670
msgid "Unknown"
msgstr "Неизвестный"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:505
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513
msgid "TrackerErr"
msgstr "ОшибкаТрекера"
# TODO should replace "uploader limit NN peers" with "global number of upload slots: NN"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:507
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:519
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:521
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:528
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:530
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:534
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:536
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:862
msgid "peers"
msgstr "пир."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:521
msgid "Seeding"
msgstr "Раздается"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:523
msgid "Complete"
msgstr "Завершен"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:526
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:530
msgid "OK"
msgstr "Загружается"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:532
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:536
msgid "Stalled"
msgstr "Простаивает"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:538
msgid "No Peers"
msgstr "Нет Пиров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540
msgid "Stopped"
msgstr "Остановлен"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:553
msgid "View files"
msgstr "Открыть директорию"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555
msgid "Open file"
msgstr "Открыть файл"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:579
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:781
msgid "Tracker"
msgstr "Трекер"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:580
msgid "Details"
msgstr "Подробнее"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:614
msgid "Stop the torrent"
msgstr "Остановить торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:616
msgid "Stop"
msgstr "Остановить"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622
msgid "Start the torrent"
msgstr "Запустить торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:624
msgid "Start"
msgstr "Запустить"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:629
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Удалить торрент из списка и с диска"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631
msgid "Remove"
msgstr "Удалить"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:635
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Удалить торрент и стереть загруженные файлы"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:637
msgid "Delete"
msgstr "Стереть"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
msgid "Seed"
msgstr "Сид"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:698
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "Uninteresting (У пира нет нужных нам частей торрента)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:700
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "Choked (Этот пир не позволяет нам запрашивать части торрента)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:714
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "Uninterested (У нас нужных этому пиру частей торрента)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:716
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Choking (Мы не позволяем этому пиру запрашивать у нас части торрента)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:743
msgid "Add Torrent"
msgstr "Добавить Торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:745
msgid "From URL"
msgstr "Из URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750
msgid "Add torrent"
msgstr "Добавить торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:753
#, java-format
msgid "Alternately, you can copy .torrent files to the directory {0}."
msgstr "Ну или вы можете скопировать .torrent-файлы в директорию {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:755
msgid "Removing a .torrent file will cause the torrent to stop."
msgstr "Удаление .torrent-файла приведет к остановке торрента."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:772
msgid "Create Torrent"
msgstr "Создать Торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:775
msgid "Data to seed"
msgstr "Файлы для раздачи"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:779
msgid "File or directory to seed (must be within the specified path)"
msgstr "Файл или директория для раздачи (вводите только название файла или директории, указание абсолютных путей не поддерживается)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:783
msgid "Select a tracker"
msgstr "Выбрать трекер"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
msgid "or"
msgstr "или"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:799
msgid "Specify custom tracker announce URL"
msgstr "Задать URL анонсера вручную"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:802
msgid "Create torrent"
msgstr "Создать торрент"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820
msgid "Configuration"
msgstr "Настройки"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823
msgid "Data directory"
msgstr "Директория для файлов"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826
msgid "Directory to store torrents and data"
msgstr "Директория, где будут храниться торренты и загружаемые файлы"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828
msgid "Edit i2psnark.config and restart to change"
msgstr "Для изменения отредактируйте файл i2psnark.config и перезагрузите I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:832
msgid "Auto start"
msgstr "Автозапуск"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
msgid "If checked, automatically start torrents that are added"
msgstr "Автоматически запускать торренты после добавления"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:859
msgid "Total uploader limit"
msgstr "Ограничение количества слотов отдачи"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:866
msgid "Up bandwidth limit"
msgstr "Ограничение скорости отдачи"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:869
msgid "Half available bandwidth recommended."
msgstr "Рекомендуется использовать половину от доступной пропускной способности."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:871
msgid "View or change router bandwidth"
msgstr "Посмотреть/настроить ограничения скорости в маршрутизаторе I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:875
msgid "Use open trackers also"
msgstr "Дополнительно использовать открытые трекеры"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:879
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
msgstr "Анонсировать торренты на открытых трекерах, дополнительно к тем, что указаны внутри торрента"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:883
msgid "Open tracker announce URLs"
msgstr "URL открытых трекеров"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:894
msgid "I2CP host"
msgstr "Адрес I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:899
msgid "I2CP port"
msgstr "Порт I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:912
msgid "I2CP options"
msgstr "Параметры I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:917
msgid "Save configuration"
msgstr "Сохранить настройки"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Получен торрент из: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:998
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Торрент полученный из {0} некорректен"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1003
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Не удалось получить торрент из: {0}"

View File

@ -0,0 +1,652 @@
# 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-01-29 07:17+0000\n"
"PO-Revision-Date: 2010-01-29 15:30+0800\n"
"Last-Translator: walking <zhazhenzhong@gmail.com>\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: Chinese\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:84
#, java-format
msgid "Adding torrents in {0} minutes"
msgstr "{0}分钟内完成添加"
#: ../java/src/org/klomp/snark/SnarkManager.java:241
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:243
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:255
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "上传带宽限制改为 {0} KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:257
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "最小上传带宽限制为 {0} KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:301
msgid "Cannot change the I2CP settings while torrents are active"
msgstr "正在下载/上传无法更改I2CP设置"
#: ../java/src/org/klomp/snark/SnarkManager.java:307
msgid "Disconnecting old I2CP destination"
msgstr "正在断开旧的I2CP目标"
#: ../java/src/org/klomp/snark/SnarkManager.java:311
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "I2CP设置改为{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:315
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "无法通过新设置连接恢复I2CP的旧设置"
#: ../java/src/org/klomp/snark/SnarkManager.java:319
msgid "Unable to reconnect with the old settings!"
msgstr "旧设置也无法连接!"
#: ../java/src/org/klomp/snark/SnarkManager.java:321
msgid "Reconnected on the new I2CP destination"
msgstr "重新连接新I2CP目标"
#: ../java/src/org/klomp/snark/SnarkManager.java:332
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "\"{0}\"的I2CP监听端口已启动"
#: ../java/src/org/klomp/snark/SnarkManager.java:343
msgid "Enabled autostart"
msgstr "启用自动启动"
#: ../java/src/org/klomp/snark/SnarkManager.java:345
msgid "Disabled autostart"
msgstr "禁用自动启动"
#: ../java/src/org/klomp/snark/SnarkManager.java:351
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "启用OpenTracker-重新启动种子后生效"
#: ../java/src/org/klomp/snark/SnarkManager.java:353
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "禁用OpenTracker - 重新启动种子后生效"
#: ../java/src/org/klomp/snark/SnarkManager.java:360
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr "OpenTracker列表已改变 - 重新启动种子后生效"
#: ../java/src/org/klomp/snark/SnarkManager.java:367
msgid "Configuration unchanged."
msgstr "设置未改变"
#: ../java/src/org/klomp/snark/SnarkManager.java:377
#, java-format
msgid "Unable to save the config to {0}"
msgstr "无法保存设置到{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:395
msgid "Connecting to I2P"
msgstr "正在连接到I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:398
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "连接I2P时发生错误 - 请检查I2CP设置!"
#: ../java/src/org/klomp/snark/SnarkManager.java:407
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "错误:无法添加种子{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:446
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "无效种子 \"{0}\" "
#: ../java/src/org/klomp/snark/SnarkManager.java:461
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "已添加并启动种子:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:463
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "已添加种子:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:559
#, java-format
msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
msgstr "【匿名性警告】\"{0}\" 中含有非I2P Tracker程序将从Tracker列表中将其删除。"
#: ../java/src/org/klomp/snark/SnarkManager.java:562
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "\"{0}\" ({1}) 含有太多文件,删除之!"
#: ../java/src/org/klomp/snark/SnarkManager.java:564
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "种子文件 \"{0}\" 不以 \".torrent\"结尾,正在删除!"
#: ../java/src/org/klomp/snark/SnarkManager.java:566
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "\"{0}\" 中没有数据片,删除之!"
#: ../java/src/org/klomp/snark/SnarkManager.java:568
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "\"{0}\" 中文件分片太多,限额为{1},删除之!"
#: ../java/src/org/klomp/snark/SnarkManager.java:570
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "\"{0}\" ({1}B) 中文件分片过大,删除之。"
#: ../java/src/org/klomp/snark/SnarkManager.java:571
#, java-format
msgid "Limit is {0}B"
msgstr "限额为 {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:579
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "目前不支持大于{0}B 的种子,正在删除\"{1}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:595
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "错误:无法删除种子{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:616
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "种子已停止:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:631
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "种子已删除:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:664
#, java-format
msgid "Download finished: \"{0}\""
msgstr "下载已完成:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:664
#, java-format
msgid "size: {0}B"
msgstr "大小:{0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:692
msgid "Unable to connect to I2P!"
msgstr "无法连接至I2P!"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:86
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - 匿名BitTorrent客户端"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:95
msgid "Refresh page"
msgstr "刷新页面"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:97
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:656
msgid "I2PSnark"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:99
msgid "Forum"
msgstr "论坛"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:125
msgid "Status"
msgstr "状态"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:131
msgid "Hide Peers"
msgstr "隐藏用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:134
msgid "Show Peers"
msgstr "显示用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:139
msgid "Torrent"
msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:141
msgid "ETA"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:143
msgid "Downloaded"
msgstr "已下载"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:145
msgid "Uploaded"
msgstr "已上传"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:147
msgid "Down Rate"
msgstr "下载速度"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:149
msgid "Up Rate"
msgstr "上传速度"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:156
msgid "Stop all torrents and the I2P tunnel"
msgstr "停止全部种子及I2P隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:158
msgid "Stop All"
msgstr "停止全部"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:163
msgid "Start all torrents and the I2P tunnel"
msgstr "启动全部种子及I2P隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:165
msgid "Start All"
msgstr "启动全部"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:182
msgid "No torrents loaded."
msgstr "未载入任何种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:187
msgid "Totals"
msgstr "总计"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:189
#, java-format
msgid "{0} torrents"
msgstr "{0} 个种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:192
#, java-format
msgid "{0} connected peers"
msgstr "{0} 已连接用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:227
#, java-format
msgid "Torrent file {0} does not exist"
msgstr "种子文件{0}不存在"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:237
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:990
#, java-format
msgid "Torrent already running: {0}"
msgstr "种子已启动:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:239
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:992
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "种子排队中:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:243
#, java-format
msgid "Copying torrent to {0}"
msgstr "正在复制种子到{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:246
#, java-format
msgid "Unable to copy the torrent to {0}"
msgstr "无法复制种子文件到{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:246
#, java-format
msgid "from {0}"
msgstr "来源{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254
#, java-format
msgid "Fetching {0}"
msgstr "正在获取{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:258
msgid "Invalid URL - must start with http://"
msgstr "无效链接 - 必须以http:// 开头"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288
#, java-format
msgid "Starting up torrent {0}"
msgstr "正在启动种子{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:326
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "种子文件已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:332
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
#, java-format
msgid "Data file deleted: {0}"
msgstr "数据文件已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:334
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:344
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "无法删除数据文件:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353
#, java-format
msgid "Data dir deleted: {0}"
msgstr "数据文件夹已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:384
msgid "Error creating torrent - you must select a tracker"
msgstr "创建种子时发生错误 - 您必须选择一个Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:399
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "种子创建成功\"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:402
#, java-format
msgid "Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\""
msgstr "多数I2PTracker需要用户在做种前注册新种子 - 请在启动 \"{0}\"前到所使用的Tracker进行注册。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:404
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "创建种子时发生错误 \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "无法为不存在的数据文件创建种子:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:410
msgid "Error creating torrent - you must enter a file or directory"
msgstr "创建种子时发生错误 - 必须指定文件或文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "正在停用所有种子并关闭I2P隧道。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:422
msgid "I2P tunnel closed."
msgstr "I2P隧道已关闭"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "正在打开I2P隧道并启动所有种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:502
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670
msgid "Unknown"
msgstr "未知"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:505
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513
msgid "TrackerErr"
msgstr "Tracker错误"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:507
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:509
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:519
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:521
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:528
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:530
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:534
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:536
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:862
msgid "peers"
msgstr "用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:521
msgid "Seeding"
msgstr "正做种"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:523
msgid "Complete"
msgstr "完成"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:526
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:530
msgid "OK"
msgstr "确定"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:532
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:536
msgid "Stalled"
msgstr "等待"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:538
msgid "No Peers"
msgstr "没有用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540
msgid "Stopped"
msgstr "已停用"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:553
msgid "View files"
msgstr "浏览文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555
msgid "Open file"
msgstr "打开文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:579
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:781
msgid "Tracker"
msgstr "Tracker服务器"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:580
msgid "Details"
msgstr "详情"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:614
msgid "Stop the torrent"
msgstr "停止种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:616
msgid "Stop"
msgstr "停止"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622
msgid "Start the torrent"
msgstr "启动种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:624
msgid "Start"
msgstr "启动"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:629
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "取消下载任务并删除对应种子文件。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631
msgid "Remove"
msgstr "移除"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:635
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "删除种子及所下载的文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:637
msgid "Delete"
msgstr "删除"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
msgid "Seed"
msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:698
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "无需要部分"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:700
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "拒绝请求"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:714
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "无需要部分"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:716
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "拒绝请求"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:743
msgid "Add Torrent"
msgstr "添加种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:745
msgid "From URL"
msgstr "从URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750
msgid "Add torrent"
msgstr "添加种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:753
#, java-format
msgid "Alternately, you can copy .torrent files to the directory {0}."
msgstr "或者您可以将.torrent文件复制到以下目录{0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:755
msgid "Removing a .torrent file will cause the torrent to stop."
msgstr "删除种子文件将导致中止该下载任务。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:772
msgid "Create Torrent"
msgstr "创建种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:775
msgid "Data to seed"
msgstr "做种数据"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:779
msgid "File or directory to seed (must be within the specified path)"
msgstr "做种文件或文件夹(必须下面为Snark指定的文件夹中)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:783
msgid "Select a tracker"
msgstr "选择一个Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:796
msgid "or"
msgstr "或"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:799
msgid "Specify custom tracker announce URL"
msgstr "指定Open Tracker发布链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:802
msgid "Create torrent"
msgstr "创建种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820
msgid "Configuration"
msgstr "设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823
msgid "Data directory"
msgstr "数据文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826
msgid "Directory to store torrents and data"
msgstr "种子及被做种文件的保存位置。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828
msgid "Edit i2psnark.config and restart to change"
msgstr "编辑 i2psnark.config 并重启Snark后生效"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:832
msgid "Auto start"
msgstr "自动启动"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
msgid "If checked, automatically start torrents that are added"
msgstr "选中后Snark将自动启动已添加的所有种子。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:859
msgid "Total uploader limit"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:866
msgid "Up bandwidth limit"
msgstr "上传带宽限制"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:869
msgid "Half available bandwidth recommended."
msgstr "推荐设置为可用带宽的一半。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:871
msgid "View or change router bandwidth"
msgstr "浏览或修改路由器带宽"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:875
msgid "Use open trackers also"
msgstr "同时使用OpenTracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:879
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
msgstr "选择后在OpenTracker及种子文件中的Tracker上同时发布。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:883
msgid "Open tracker announce URLs"
msgstr "Open Tracker发布链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:894
msgid "I2CP host"
msgstr "I2CP主机"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:899
msgid "I2CP port"
msgstr "I2CP端口"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:912
msgid "I2CP options"
msgstr "I2CP选项"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:917
msgid "Save configuration"
msgstr "保存设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970
#, java-format
msgid "Torrent fetched from {0}"
msgstr "从{0}获取种子成功"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:998
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "{0}的种子中有错误"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1003
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "从{0}获得种子失败"
#~ msgid "Custom tracker URL"
#~ msgstr "自定义TrackerURL"
#~ msgid "Configure"
#~ msgstr "设置"

View File

@ -0,0 +1,17 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
# zzz - public domain
#
## launching sh.exe with -login parameter will open a shell with the current path always pointing to \bin\
## need to cd into our orignal path - where we call sh.exe from.
cd $CALLFROM
## echo $PWD
## except this everything is the same with bundle-message.sh
## walking - public domain :-D
source bundle-messages.sh $PARAS

View File

@ -41,13 +41,48 @@
<attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
</manifest>
</jar>
<ant target="bundle" />
<ant target="war" />
</target>
<target name="bundle" depends="compile, precompilejsp">
<!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="false" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
</exec>
</target>
<target name="poupdate" depends="compile, precompilejsp">
<!-- Update the messages_*.po files. -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="true" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
<arg value="-p" />
</exec>
</target>
<target name="war" depends="precompilejsp">
<war destfile="build/i2ptunnel.war" webxml="../jsp/web-out.xml"
basedir="../jsp/" excludes="web.xml, **/*.java, *.jsp">
</war>
</target>
<target name="precompilejsp" unless="precompilejsp.uptodate">
<delete dir="../jsp/WEB-INF/" />
<delete file="../jsp/web-fragment.xml" />
@ -113,11 +148,7 @@
<delete file="../jsp/web-out.xml" />
</target>
<target name="cleandep" depends="clean">
<!-- ministreaming will clean core -->
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
<target name="distclean" depends="clean">
<!-- ministreaming will clean core -->
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
</project>

View File

@ -0,0 +1,26 @@
@echo off
set Callfrom=%cd%
set Paras=%1
rem before calling make sure you have msys and mingw 's "bin" path
rem in your current searching path
rem type "set path" to check
if not exist ..\locale\*.only goto updateALL
rem put a messages_xx.only(eg messages_zh.only) into locale folder
rem this script will only touch the po file(eg zh) you specified, leaving other po files untact.
for %%i in (..\locale\*.only) do set PO=%%~ni
echo [Notice] Yu choose to Ony update the choosen file: %PO%.po
for %%i in (..\locale\*.po) do if not %%~ni==%PO% ren %%i %%~ni.po-
call sh --login %cd%\bmsg.sh
for %%i in (..\locale\*.po-) do if not %%~ni==%PO% ren %%i %%~ni.po
goto end
:updateALL
call sh --login %cd%\bmsg.sh
:end
echo End of Message Bundling

View File

@ -0,0 +1,87 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
#
# usage:
# bundle-messages.sh (generates the resource bundle from the .po file)
# bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle)
#
# zzz - public domain
#
CLASS=net.i2p.i2ptunnel.web.messages
TMPFILE=build/javafiles.txt
export TZ=UTC
if [ "$1" = "-p" ]
then
POUPDATE=1
fi
# add ../java/ so the refs will work in the po file
JPATHS="../java/src ../jsp/WEB-INF"
for i in ../locale/messages_*.po
do
# get language
LG=${i#../locale/messages_}
LG=${LG%.po}
if [ "$POUPDATE" = "1" ]
then
# make list of java files newer than the .po file
find $JPATHS -name *.java -newer $i > $TMPFILE
fi
if [ -s ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/web/messages_$LG.class -a \
../jsp/WEB-INF/classes/net/i2p/i2ptunnel/web/messages_$LG.class -nt $i -a \
! -s $TMPFILE ]
then
continue
fi
if [ "$POUPDATE" = "1" ]
then
echo "Updating the $i file from the tags..."
# extract strings from java and jsp files, and update messages.po files
# translate calls must be one of the forms:
# _("foo")
# _x("foo")
# intl._("foo")
# intl.title("foo")
# In a jsp, you must use a helper or handler that has the context set.
# To start a new translation, copy the header from an old translation to the new .po file,
# then ant distclean updater.
find $JPATHS -name *.java > $TMPFILE
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 \
--keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
-o ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - xgettext failed, not updating translations'
rm -f ${i}t
break
fi
msgmerge -U --backup=none $i ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - msgmerge failed, not updating translations'
rm -f ${i}t
break
fi
rm -f ${i}t
# so we don't do this again
touch $i
fi
echo "Generating ${CLASS}_$LG ResourceBundle..."
# convert to class files in build/obj
msgfmt --java --statistics -r $CLASS -l $LG -d ../jsp/WEB-INF/classes $i
if [ $? -ne 0 ]
then
echo 'Warning - msgfmt failed, not updating translations'
break
fi
done
rm -f $TMPFILE
# todo: return failure
exit 0

View File

@ -1,72 +0,0 @@
/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java)
* (c) 2003 - 2004 mihi
*/
package net.i2p.i2ptunnel;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import net.i2p.util.Log;
/**
* Read what i2ptunnel logs, and expose it in a buffer
*
*/
class BufferLogger implements Logging {
private final static Log _log = new Log(BufferLogger.class);
private ByteArrayOutputStream _baos; // FIXME should be final and use a factory. FIXME
private boolean _ignore;
/**
* Constructs a buffered logger.
*/
public BufferLogger() {
_baos = new ByteArrayOutputStream(512);
_ignore = false;
}
private final static String EMPTY = "";
/**
* Retrieves the buffer
* @return the buffer
*/
public String getBuffer() {
if (_ignore)
return EMPTY;
return new String(_baos.toByteArray());
}
/**
* We don't care about anything else the logger receives. This is useful
* for loggers passed in to servers and clients, since they will continue
* to add info to the logger, but if we're instantiated by the tunnel manager,
* its likely we only care about the first few messages it sends us.
*
*/
public void ignoreFurtherActions() {
_ignore = true;
synchronized (_baos) {
_baos.reset();
}
_baos = null;
}
/**
* Pass in some random data
* @param s String containing what we're logging.
*/
public void log(String s) {
if (_ignore) return;
if (s != null) {
_log.debug("logging [" + s + "]");
try {
_baos.write(s.getBytes());
_baos.write('\n');
} catch (IOException ioe) {
_log.error("Error logging [" + s + "]");
}
}
}
}

View File

@ -20,7 +20,7 @@ import java.util.zip.GZIPInputStream;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -219,7 +219,7 @@ class HTTPResponseOutputStream extends FilterOutputStream {
//out.flush();
PipedInputStream pi = new PipedInputStream();
PipedOutputStream po = new PipedOutputStream(pi);
new I2PThread(new Pusher(pi, out), "HTTP decompresser").start();
new I2PAppThread(new Pusher(pi, out), "HTTP decompresser").start();
out = po;
}

View File

@ -236,6 +236,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
runServer(args, l);
} else if ("httpserver".equals(cmdname)) {
runHttpServer(args, l);
} else if ("httpbidirserver".equals(cmdname)) {
runHttpBidirServer(args, l);
} else if ("ircserver".equals(cmdname)) {
runIrcServer(args, l);
} else if ("textserver".equals(cmdname)) {
@ -300,6 +302,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("ping <args>");
l.log("server <host> <port> <privkeyfile>");
l.log("httpserver <host> <port> <spoofedhost> <privkeyfile>");
l.log("httpbidirserver <host> <port> <proxyport> <spoofedhost> <privkeyfile>");
l.log("textserver <host> <port> <privkey>");
l.log("genkeys <privkeyfile> [<pubkeyfile>]");
l.log("gentextkeys");
@ -503,6 +506,80 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
/**
* Run the HTTP server pointing at the host and port specified using the private i2p
* destination loaded from the specified file, replacing the HTTP headers
* so that the Host: specified is the one spoofed. Also runs an HTTP proxy for
* bidirectional communications on the same tunnel destination.<p />
*
* Sets the event "serverTaskId" = Integer(taskId) after the tunnel has been started (or -1 on error)
* Also sets the event "openServerResult" = "ok" or "error" (displaying "Ready!" on the logger after
* 'ok'). So, success = serverTaskId != -1 and openServerResult = ok.
*
* @param args {hostname, portNumber, proxyPortNumber, spoofedHost, privKeyFilename}
* @param l logger to receive events and output
*/
public void runHttpBidirServer(String args[], Logging l) {
if (args.length == 5) {
InetAddress serverHost = null;
int portNum = -1;
int port2Num = -1;
File privKeyFile = null;
try {
serverHost = InetAddress.getByName(args[0]);
} catch (UnknownHostException uhe) {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
try {
portNum = Integer.parseInt(args[1]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
try {
port2Num = Integer.parseInt(args[2]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[2], nfe);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
String spoofedHost = args[3];
privKeyFile = new File(args[4]);
if (!privKeyFile.isAbsolute())
privKeyFile = new File(_context.getConfigDir(), args[4]);
if (!privKeyFile.canRead()) {
l.log("private key file does not exist");
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[4]);
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
I2PTunnelHTTPBidirServer serv = new I2PTunnelHTTPBidirServer(serverHost, portNum, port2Num, privKeyFile, args[3], spoofedHost, l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
return;
} else {
l.log("httpserver <host> <port> <proxyport> <spoofedhost> <privkeyfile>");
l.log(" creates a bidirectional HTTP server that sends all incoming data\n"
+ " of its destination to host:port., filtering the HTTP\n"
+ " headers so it looks like the request is to the spoofed host,"
+ " and listens to host:proxyport to proxy HTTP requests.");
notifyEvent("serverTaskId", Integer.valueOf(-1));
}
}
/**
* Run the server pointing at the host and port specified using the private i2p
* destination loaded from the given base64 stream. <p />

View File

@ -27,7 +27,7 @@ import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
@ -67,7 +67,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
// private Object conLock = new Object();
/** List of Socket for those accept()ed but not yet started up */
private List _waitingSockets = new ArrayList(); // FIXME should be final and use a factory. FIXME
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? */
@ -89,12 +89,52 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private static final int DEFAULT_NUM_CONNECTION_BUILDERS = 5;
private static final int DEFAULT_MAX_WAIT_TIME = 30*1000;
//public I2PTunnelClientBase(int localPort, boolean ownDest,
// Logging l) {
// I2PTunnelClientBase(localPort, ownDest, l, (EventDispatcher)null);
//}
// true if we are chained from a server.
private boolean chained = false;
public I2PTunnelClientBase(int localPort, Logging l, I2PSocketManager sktMgr,
I2PTunnel tunnel, EventDispatcher notifyThis, long clientId )
throws IllegalArgumentException {
super(localPort + " (uninitialized)", notifyThis, tunnel);
chained = true;
sockMgr = sktMgr;
_clientId = clientId;
this.localPort = localPort;
this.l = l;
this.handlerName = handlerName + _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 });
Thread t = new I2PAppThread(this);
t.setName("Client " + _clientId);
listenerReady = false;
t.start();
open = true;
synchronized (this) {
while (!listenerReady && open) {
try {
wait();
} catch (InterruptedException e) {
// ignore
}
}
}
configurePool(tunnel);
if (open && listenerReady) {
l.log("Ready! Port " + getLocalPort());
notifyEvent("openBaseClientResult", "ok");
} else {
l.log("Error listening - please see the logs!");
notifyEvent("openBaseClientResult", "error");
}
}
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
EventDispatcher notifyThis, String handlerName,
I2PTunnel tunnel) throws IllegalArgumentException {
@ -153,7 +193,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
} // else delay creating session until createI2PSocket() is called
Thread t = new I2PThread(this);
Thread t = new I2PAppThread(this);
t.setName("Client " + _clientId);
listenerReady = false;
t.start();
@ -188,7 +228,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
*
*/
private void configurePool(I2PTunnel tunnel) {
_waitingSockets = new ArrayList(4);
//_waitingSockets = new ArrayList(4);
Properties opts = tunnel.getClientOptions();
String maxWait = opts.getProperty(PROP_MAX_WAIT_TIME, DEFAULT_MAX_WAIT_TIME+"");
@ -207,7 +247,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
for (int i = 0; i < _numConnectionBuilders; i++) {
String name = "ClientBuilder" + _clientId + '.' + i;
I2PThread b = new I2PThread(new TunnelConnectionBuilder(), name);
I2PAppThread b = new I2PAppThread(new TunnelConnectionBuilder(), name);
b.setDaemon(true);
b.start();
}
@ -350,7 +390,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* called by derived classes after initialization.
*
*/
public final void startRunning() {
public void startRunning() {
synchronized (startLock) {
startRunning = true;
startLock.notify();
@ -490,7 +530,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
protected void manageConnection(Socket s) {
if (s == null) return;
if (_numConnectionBuilders <= 0) {
new I2PThread(new BlockingRunner(s), "Clinet run").start();
new I2PAppThread(new BlockingRunner(s), "Clinet run").start();
return;
}
@ -559,10 +599,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
return false;
}
I2PSession session = sockMgr.getSession();
if (session != null) {
getTunnel().removeSession(session);
}
if (!chained) {
I2PSession session = sockMgr.getSession();
if (session != null) {
getTunnel().removeSession(session);
}
} // else the app chaining to this one closes it!
}
l.log("Closing client " + toString());
open = false;

View File

@ -0,0 +1,54 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.i2ptunnel;
// import java.util.ArrayList;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.EventDispatcher;
/**
* Reuse HTTP server's I2PSocketManager for a proxy with no outproxy capability.
*
* @author sponge
*/
public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runnable {
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router
*/
public I2PTunnelHTTPBidirProxy(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]");
startRunning();
notifyEvent("openHTTPClientResult", "ok");
}
}

View File

@ -0,0 +1,44 @@
/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java)
* (c) 2003 - 2004 mihi
*/
package net.i2p.i2ptunnel;
import java.io.File;
import java.io.InputStream;
import java.net.InetAddress;
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);
finishSetupI2PTunnelHTTPBidirServer(l, proxyport);
}
public I2PTunnelHTTPBidirServer(InetAddress host, int port, int proxyport, File privkey, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privkey, privkeyname, spoofHost, l, notifyThis, tunnel);
finishSetupI2PTunnelHTTPBidirServer(l, proxyport);
}
public I2PTunnelHTTPBidirServer(InetAddress host, int port, int proxyport, InputStream privData, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, privkeyname, spoofHost, l, notifyThis, tunnel);
finishSetupI2PTunnelHTTPBidirServer(l, proxyport);
}
private void finishSetupI2PTunnelHTTPBidirServer(Logging l, int proxyport) {
localPort = proxyport;
bidir = true;
/* start the httpclient */
task = new I2PTunnelHTTPBidirProxy(localPort, l, sockMgr, getTunnel(), getEventDispatcher(), __serverId);
sockMgr.setName("Server"); // TO-DO: Need to change this to "Bidir"!
getTunnel().addSession(sockMgr.getSession());
l.log("Ready!");
notifyEvent("openServerResult", "ok");
}
}

View File

@ -3,8 +3,10 @@
*/
package net.i2p.i2ptunnel;
import java.io.ByteArrayOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -15,12 +17,14 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
@ -29,6 +33,8 @@ import net.i2p.util.EventDispatcher;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.Translate;
/**
* Act as a mini HTTP proxy, handling various different types of requests,
* forwarding them through I2P appropriately, and displaying the reply. Supported
@ -38,7 +44,7 @@ import net.i2p.util.Log;
* $method $path $protocolVersion\nHost: $site
* or
* $method http://i2p/$b64key/$path $protocolVersion
* or
* or
* $method /$site/$path $protocolVersion
* </pre>
*
@ -51,10 +57,14 @@ import net.i2p.util.Log;
public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelHTTPClient.class);
private final List proxyList;
protected final List proxyList = new ArrayList();
private HashMap addressHelpers = new HashMap();
/**
* These are backups if the xxx.ht error page is missing.
*/
private final static byte[] ERR_REQUEST_DENIED =
("HTTP/1.1 403 Access Denied\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -63,7 +73,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"<html><body><H1>I2P ERROR: REQUEST DENIED</H1>"+
"You attempted to connect to a non-I2P website or location.<BR>")
.getBytes();
private final static byte[] ERR_DESTINATION_UNKNOWN =
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -73,10 +83,11 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"That I2P Destination was not found. Perhaps you pasted in the "+
"wrong BASE64 I2P Destination or the link you are following is "+
"bad. The host (or the WWW proxy, if you're using one) could also "+
"be temporarily offline. You may want to <b>retry</b>. "+
"be temporarily offline. You may want to <b>retry</b>. "+
"Could not find the following Destination:<BR><BR><div>")
.getBytes();
/*****
private final static byte[] ERR_TIMEOUT =
("HTTP/1.1 504 Gateway Timeout\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -88,6 +99,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"destination may have issues. Could not get a response from "+
"the following Destination:<BR><BR>")
.getBytes();
*****/
private final static byte[] ERR_NO_OUTPROXY =
("HTTP/1.1 503 Service Unavailable\r\n"+
@ -98,7 +110,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"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_AHELPER_CONFLICT =
("HTTP/1.1 409 Conflict\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -108,13 +120,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"The addresshelper link you followed specifies a different destination key "+
"than a host entry in your host database. "+
"Someone could be trying to impersonate another eepsite, "+
"or people have given two eepsites identical names.<P/>"+
"or people have given two eepsites identical names.<p>"+
"You can resolve the conflict by considering which key you trust, "+
"and either discarding the addresshelper link, "+
"discarding the host entry from your host database, "+
"or naming one of them differently.<P/>")
"or naming one of them differently.<p>")
.getBytes();
private final static byte[] ERR_BAD_PROTOCOL =
("HTTP/1.1 403 Bad Protocol\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -124,7 +136,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"The request uses a bad protocol. "+
"The I2P HTTP Proxy supports http:// requests ONLY. Other protocols such as https:// and ftp:// are not allowed.<BR>")
.getBytes();
private final static byte[] ERR_LOCALHOST =
("HTTP/1.1 403 Access Denied\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
@ -133,23 +145,31 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"<html><body><H1>I2P ERROR: REQUEST DENIED</H1>"+
"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");
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]");
startRunning();
notifyEvent("openHTTPClientResult", "ok");
}
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router
*/
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest,
String wwwProxy, EventDispatcher notifyThis,
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest,
String wwwProxy, EventDispatcher notifyThis,
I2PTunnel tunnel) throws IllegalArgumentException {
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
proxyList = new ArrayList();
//proxyList = new ArrayList(); // We won't use outside of i2p
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openHTTPClientResult", "error");
return;
@ -169,7 +189,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
private String getPrefix(long requestId) { return "Client[" + _clientId + "/" + requestId + "]: "; }
private String selectProxy() {
synchronized (proxyList) {
int size = proxyList.size();
@ -186,8 +206,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
private static final int DEFAULT_READ_TIMEOUT = 60*1000;
/**
/**
* create the default options (using the default timeout, etc)
* unused?
*/
@ -203,8 +223,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
return opts;
}
/**
/**
* create the default options (using the default timeout, etc)
*
*/
@ -224,18 +244,44 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
return opts;
}
private InternalSocketRunner isr;
/**
* Actually start working on incoming connections.
* Overridden to start an internal socket too.
*
*/
@Override
public void startRunning() {
super.startRunning();
this.isr = new InternalSocketRunner(this);
}
/**
* Overridden to close internal socket too.
*/
@Override
public boolean close(boolean forced) {
boolean rv = super.close(forced);
if (this.isr != null)
this.isr.stopRunning();
return rv;
}
private static final boolean DEFAULT_GZIP = true;
// all default to false
public static final String PROP_REFERER = "i2ptunnel.httpclient.sendReferer";
public static final String PROP_USER_AGENT = "i2ptunnel.httpclient.sendUserAgent";
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;
String targetRequest = null;
boolean usingWWWProxy = false;
boolean usingInternalServer = false;
String currentProxy = null;
long requestId = ++__requestId;
try {
@ -248,20 +294,21 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
line = line.trim();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + "Line=[" + line + "]");
String lowercaseLine = line.toLowerCase();
if (lowercaseLine.startsWith("connection: ") ||
lowercaseLine.startsWith("keep-alive: ") ||
if (lowercaseLine.startsWith("connection: ") ||
lowercaseLine.startsWith("keep-alive: ") ||
lowercaseLine.startsWith("proxy-connection: "))
continue;
if (method == null) { // first line (GET /base64/realaddr)
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + "Method is null for [" + line + "]");
int pos = line.indexOf(" ");
if (pos == -1) break;
method = line.substring(0, pos);
// TODO use Java URL class to make all this simpler and more robust
String request = line.substring(pos + 1);
if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
request = "http://i2p" + request;
@ -293,7 +340,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
break;
}
host = request.substring(0, pos);
// parse port
int posPort = host.indexOf(":");
int port = 80;
@ -306,9 +353,12 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
// TODO: log this
}
}
// Quick hack for foo.bar.i2p
if (host.toLowerCase().endsWith(".i2p")) {
if (host.toLowerCase().equals("proxy.i2p")) {
// so we don't do any naming service lookups
destination = "proxy.i2p";
usingInternalServer = true;
} else if (host.toLowerCase().endsWith(".i2p")) {
// Destination gets the host name
destination = host;
// Host becomes the destination key
@ -320,7 +370,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
// and split the request into it's component parts for rebuilding later
String ahelperKey = null;
boolean ahelperConflict = false;
String fragments = request.substring(pos2 + 1);
String uriPath = request.substring(0, pos2);
pos2 = fragments.indexOf(" ");
@ -334,15 +384,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
pos2 = fragments.indexOf("&");
fragment = fragments.substring(0, pos2);
fragments = fragments.substring(pos2 + 1);
// Fragment looks like addresshelper key
if (fragment.startsWith("i2paddresshelper=")) {
pos2 = fragment.indexOf("=");
ahelperKey = fragment.substring(pos2 + 1);
// Key contains data, lets not ignore it
if (ahelperKey != null) {
// Host resolvable only with addresshelper
if ( (host == null) || ("i2p".equals(host)) )
{
@ -366,32 +416,26 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if ("".equals(urlEncoding)) {
urlEncoding = "?" + fragment;
} else {
urlEncoding = urlEncoding + "&" + fragment;
urlEncoding = urlEncoding + "&" + fragment;
}
}
}
// Reconstruct the request minus the i2paddresshelper GET var
request = uriPath + urlEncoding + " " + protocolVersion;
// Did addresshelper key conflict?
if (ahelperConflict)
{
String str;
byte[] header;
str = FileUtil.readTextFile((new File(_errorDir, "ahelper-conflict-header.ht")).getAbsolutePath(), 100, true);
if (str != null) header = str.getBytes();
else header = ERR_AHELPER_CONFLICT;
if (out != null) {
long alias = I2PAppContext.getGlobalContext().random().nextLong();
String trustedURL = protocol + uriPath + urlEncoding;
String conflictURL = protocol + alias + ".i2p/?" + initialFragments;
byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
out.write(header);
out.write(("To visit the destination in your host database, click <a href=\"" + trustedURL + "\">here</a>. To visit the conflicting addresshelper link by temporarily giving it a random alias, click <a href=\"" + conflictURL + "\">here</a>.<P/>").getBytes());
out.write("</div><div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br />Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></div></body></html>\n".getBytes());
out.flush();
out.write(_("To visit the destination in your host database, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper link by temporarily giving it a random alias, click <a href=\"{1}\">here</a>.", trustedURL, conflictURL).getBytes("UTF-8"));
out.write(("<p></div>").getBytes());
writeFooter(out);
}
s.close();
return;
@ -404,15 +448,12 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
host = getHostName(destination);
ahelper = 1;
}
line = method + " " + request.substring(pos);
} else if (host.toLowerCase().equals("localhost") || host.equals("127.0.0.1")) {
if (out != null) {
out.write(ERR_LOCALHOST);
out.write("<p /><i>Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></body></html>\n".getBytes());
out.flush();
out.write(getErrorPage("localhost", ERR_LOCALHOST));
writeFooter(out);
}
s.close();
return;
@ -430,11 +471,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
_log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
l.log("No HTTP outproxy found for the request.");
if (out != null) {
out.write(ERR_NO_OUTPROXY);
out.write("<p /><i>Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></body></html>\n".getBytes());
out.flush();
out.write(getErrorPage("noproxy", ERR_NO_OUTPROXY));
writeFooter(out);
}
s.close();
return;
@ -449,26 +487,23 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (pos < 0) {
l.log("Invalid request url [" + request + "]");
if (out != null) {
out.write(ERR_REQUEST_DENIED);
out.write("<p /><i>Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></body></html>\n".getBytes());
out.flush();
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
writeFooter(out);
}
s.close();
return;
}
destination = request.substring(0, pos);
line = method + " " + request.substring(pos);
}
} // end host name processing
boolean isValid = usingWWWProxy || isSupportedAddress(host, protocol);
boolean isValid = usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
if (!isValid) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "notValid(" + host + ")");
method = null;
destination = null;
break;
} else if (!usingWWWProxy) {
} else if ((!usingWWWProxy) && (!usingInternalServer)) {
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix(requestId) + "host=getHostName(" + destination + ")");
host = getHostName(destination); // hide original host
}
@ -479,11 +514,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
_log.debug(getPrefix(requestId) + "HOST :" + host + ":");
_log.debug(getPrefix(requestId) + "DEST :" + destination + ":");
}
// end first line processing
} else {
if (lowercaseLine.startsWith("host: ") && !usingWWWProxy) {
line = "Host: " + host;
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix(requestId) + "Setting host = " + host);
} else if (lowercaseLine.startsWith("user-agent: ") &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue()) {
@ -511,14 +548,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
continue; // completely strip the line
}
}
if (line.length() == 0) {
String ok = getTunnel().getClientOptions().getProperty("i2ptunnel.gzip");
boolean gzip = DEFAULT_GZIP;
if (ok != null)
gzip = Boolean.valueOf(ok).booleanValue();
if (gzip) {
if (gzip && !usingInternalServer) {
// according to rfc2616 s14.3, this *should* force identity, even if
// an explicit q=0 for gzip doesn't. tested against orion.i2p, and it
// seems to work.
@ -532,7 +569,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
} else {
newRequest.append(line).append("\r\n"); // HTTP spec
}
}
} // end header processing
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + "NewRequest header: [" + newRequest.toString() + "]");
@ -540,24 +578,21 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
l.log("No HTTP method found in the request.");
if (out != null) {
if ("http://".equalsIgnoreCase(protocol))
out.write(ERR_REQUEST_DENIED);
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
else
out.write(ERR_BAD_PROTOCOL);
out.write("<p /><i>Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></body></html>\n".getBytes());
out.flush();
out.write(getErrorPage("protocol", ERR_BAD_PROTOCOL));
writeFooter(out);
}
s.close();
return;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix(requestId) + "Destination: " + destination);
// Serve local proxy files (images, css linked from error pages)
// Ignore all the headers
if (destination.equals("proxy.i2p")) {
if (usingInternalServer) {
serveLocalFile(out, method, targetRequest);
s.close();
return;
@ -568,29 +603,26 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
//l.log("Could not resolve " + destination + ".");
if (_log.shouldLog(Log.WARN))
_log.warn("Unable to resolve " + destination + " (proxy? " + usingWWWProxy + ", request: " + targetRequest);
String str;
byte[] header;
boolean showAddrHelper = false;
String jumpServers = null;
if (usingWWWProxy)
str = FileUtil.readTextFile((new File(_errorDir, "dnfp-header.ht")).getAbsolutePath(), 100, true);
header = getErrorPage("dnfp", ERR_DESTINATION_UNKNOWN);
else if(ahelper != 0)
str = FileUtil.readTextFile((new File(_errorDir, "dnfb-header.ht")).getAbsolutePath(), 100, true);
header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
else if (destination.length() == 60 && destination.endsWith(".b32.i2p"))
str = FileUtil.readTextFile((new File(_errorDir, "dnf-header.ht")).getAbsolutePath(), 100, true);
header = getErrorPage("dnf", ERR_DESTINATION_UNKNOWN);
else {
str = FileUtil.readTextFile((new File(_errorDir, "dnfh-header.ht")).getAbsolutePath(), 100, true);
showAddrHelper = true;
header = getErrorPage("dnfh", ERR_DESTINATION_UNKNOWN);
jumpServers = getTunnel().getClientOptions().getProperty(PROP_JUMP_SERVERS);
if (jumpServers == null)
jumpServers = DEFAULT_JUMP_SERVERS;
}
if (str != null)
header = str.getBytes();
else
header = ERR_DESTINATION_UNKNOWN;
writeErrorMessage(header, out, targetRequest, usingWWWProxy, destination, showAddrHelper);
writeErrorMessage(header, out, targetRequest, usingWWWProxy, destination, jumpServers);
s.close();
return;
}
String remoteID;
Properties opts = new Properties();
//opts.setProperty("i2p.streaming.inactivityTimeout", ""+120*1000);
// 1 == disconnect. see ConnectionOptions in the new streaming lib, which i
@ -658,6 +690,64 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
}
/**
* foo => errordir/foo-header_xx.ht for lang xx, or errordir/foo-header.ht,
* or the backup byte array on fail.
*
* .ht files must be UTF-8 encoded and use \r\n terminators so the
* HTTP headers are conformant.
* We can't use FileUtil.readFile() because it strips \r
*
* @return non-null
*/
private byte[] getErrorPage(String base, byte[] backup) {
return getErrorPage(getTunnel().getContext(), base, backup);
}
private static byte[] getErrorPage(I2PAppContext ctx, String base, byte[] backup) {
File errorDir = new File(ctx.getBaseDir(), "docs");
String lang = ctx.getProperty("routerconsole.lang", Locale.getDefault().getLanguage());
if (lang != null && lang.length() > 0 && !lang.equals("en")) {
File file = new File(errorDir, base + "-header_" + lang + ".ht");
try {
return readFile(file);
} catch (IOException ioe) {
// try the english version now
}
}
File file = new File(errorDir, base + "-header.ht");
try {
return readFile(file);
} catch (IOException ioe) {
return backup;
}
}
private static byte[] readFile(File file) throws IOException {
FileInputStream fis = null;
byte[] buf = new byte[512];
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
try {
int len = 0;
fis = new FileInputStream(file);
while ((len = fis.read(buf)) > 0) {
baos.write(buf, 0, len);
}
return baos.toByteArray();
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
// we won't ever get here
}
private static void writeFooter(OutputStream out) throws IOException {
// the css is hiding this div for now, but we'll keep it here anyway
out.write("<div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></div></body></html>\n".getBytes());
out.flush();
}
private static class OnTimeout implements Runnable {
private Socket _socket;
private OutputStream _out;
@ -676,21 +766,22 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
public void run() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Timeout occured requesting " + _target);
handleHTTPClientException(new RuntimeException("Timeout"), _out,
handleHTTPClientException(new RuntimeException("Timeout"), _out,
_target, _usingProxy, _wwwProxy, _requestId);
closeSocket(_socket);
}
}
private static String jumpServers[] = {
"http://i2host.i2p/cgi-bin/i2hostjump?",
// "http://orion.i2p/jump/",
"http://stats.i2p/cgi-bin/jump.cgi?a=",
// "http://trevorreznik.i2p/cgi-bin/jump.php?hostname=",
"http://i2jump.i2p/"
};
private static String DEFAULT_JUMP_SERVERS =
"http://i2host.i2p/cgi-bin/i2hostjump?," +
"http://stats.i2p/cgi-bin/jump.cgi?a=," +
"http://i2jump.i2p/";
/**
* @param jumpServers comma- or space-separated list, or null
*/
private static void writeErrorMessage(byte[] errMessage, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy, boolean showAddrHelper) throws IOException {
boolean usingWWWProxy, String wwwProxy, String jumpServers) throws IOException {
if (out != null) {
out.write(errMessage);
if (targetRequest != null) {
@ -705,12 +796,19 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
out.write("\">http://".getBytes());
out.write(uri.getBytes());
out.write("</a>".getBytes());
if (usingWWWProxy) out.write(("<br />WWW proxy: " + wwwProxy).getBytes());
if (showAddrHelper) {
out.write("<br /><br />Click a link below to look for an address helper by using a \"jump\" service:<br />".getBytes());
for (int i = 0; i < jumpServers.length; i++) {
if (usingWWWProxy) out.write(("<br>WWW proxy: " + wwwProxy).getBytes());
if (jumpServers != null && jumpServers.length() > 0) {
out.write("<br><br>".getBytes());
out.write(_("Click a link below to look for an address helper by using a \"jump\" service:").getBytes("UTF-8"));
out.write("<br>".getBytes());
StringTokenizer tok = new StringTokenizer(jumpServers, ", ");
while (tok.hasMoreTokens()) {
String jurl = tok.nextToken();
if (!jurl.startsWith("http://"))
continue;
// Skip jump servers we don't know
String jumphost = jumpServers[i].substring(7); // "http://"
String jumphost = jurl.substring(7); // "http://"
jumphost = jumphost.substring(0, jumphost.indexOf('/'));
try {
Destination dest = I2PTunnel.destFromName(jumphost);
@ -719,42 +817,35 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
continue;
}
out.write("<br /><a href=\"".getBytes());
out.write(jumpServers[i].getBytes());
out.write("<br><a href=\"".getBytes());
out.write(jurl.getBytes());
out.write(uri.getBytes());
out.write("\">".getBytes());
out.write(jumpServers[i].getBytes());
out.write(jurl.getBytes());
out.write(uri.getBytes());
out.write("</a>".getBytes());
}
}
}
out.write("</div><div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br />Generated on: ".getBytes());
out.write(new Date().toString().getBytes());
out.write("</i></div></body></html>\n".getBytes());
out.flush();
out.write("</div>".getBytes());
writeFooter(out);
}
}
private static void handleHTTPClientException(Exception ex, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy, long requestId) {
// static
//if (_log.shouldLog(Log.WARN))
// _log.warn(getPrefix(requestId) + "Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex);
if (out != null) {
try {
String str;
byte[] header;
if (usingWWWProxy)
str = FileUtil.readTextFile((new File(_errorDir, "dnfp-header.ht")).getAbsolutePath(), 100, true);
header = getErrorPage(I2PAppContext.getGlobalContext(), "dnfp", ERR_DESTINATION_UNKNOWN);
else
str = FileUtil.readTextFile((new File(_errorDir, "dnf-header.ht")).getAbsolutePath(), 100, true);
if (str != null)
header = str.getBytes();
else
header = ERR_DESTINATION_UNKNOWN;
writeErrorMessage(header, out, targetRequest, usingWWWProxy, wwwProxy, false);
header = getErrorPage(I2PAppContext.getGlobalContext(), "dnf", ERR_DESTINATION_UNKNOWN);
writeErrorMessage(header, out, targetRequest, usingWWWProxy, wwwProxy, null);
} catch (IOException ioe) {
// static
//_log.warn(getPrefix(requestId) + "Error writing out the 'destination was unknown' " + "message", ioe);
@ -864,4 +955,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
out.flush();
} catch (IOException ioe) {}
}
private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
/** lang in routerconsole.lang property, else current locale */
public static String _(String key) {
return Translate.getString(key, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
}
/** {0} and {1} */
public static String _(String key, Object o, Object o2) {
return Translate.getString(key, o, o2, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
}
}

View File

@ -17,7 +17,7 @@ import java.util.zip.GZIPOutputStream;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.DataHelper;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.data.Base32;
@ -39,21 +39,21 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
public I2PTunnelHTTPServer(InetAddress host, int port, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, l, notifyThis, tunnel);
_spoofHost = spoofHost;
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 });
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel", new long[] { 60*1000, 10*60*1000 });
setupI2PTunnelHTTPServer(spoofHost);
}
public I2PTunnelHTTPServer(InetAddress host, int port, File privkey, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privkey, privkeyname, l, notifyThis, tunnel);
_spoofHost = spoofHost;
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 });
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000 });
setupI2PTunnelHTTPServer(spoofHost);
}
public I2PTunnelHTTPServer(InetAddress host, int port, InputStream privData, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, privkeyname, l, notifyThis, tunnel);
_spoofHost = spoofHost;
setupI2PTunnelHTTPServer(spoofHost);
}
private void setupI2PTunnelHTTPServer(String spoofHost) {
_spoofHost = spoofHost;
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 });
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000 });
}
@ -118,7 +118,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
useGZIP = true;
if (allowGZIP && useGZIP) {
I2PThread req = new I2PThread(new CompressedRequestor(s, socket, modifiedHeader), Thread.currentThread().getName()+".hc");
I2PAppThread req = new I2PAppThread(new CompressedRequestor(s, socket, modifiedHeader), Thread.currentThread().getName()+".hc");
req.start();
} else {
new I2PTunnelRunner(s, socket, slock, null, modifiedHeader.getBytes(), null);
@ -174,7 +174,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
_log.info("request headers: " + _headers);
serverout.write(_headers.getBytes());
browserin = _browser.getInputStream();
I2PThread sender = new I2PThread(new Sender(serverout, browserin, "server: browser to server"), Thread.currentThread().getName() + "hcs");
I2PAppThread sender = new I2PAppThread(new Sender(serverout, browserin, "server: browser to server"), Thread.currentThread().getName() + "hcs");
sender.start();
browserout = _browser.getOutputStream();

View File

@ -14,7 +14,7 @@ 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.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable {
@ -83,9 +83,9 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
i2ps = createI2PSocket(clientDest);
i2ps.setReadTimeout(readTimeout);
StringBuilder expectedPong = new StringBuilder();
Thread in = new I2PThread(new IrcInboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " in");
Thread in = new I2PAppThread(new IrcInboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " in");
in.start();
Thread out = new I2PThread(new IrcOutboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " out");
Thread out = new I2PAppThread(new IrcOutboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " out");
out.start();
} catch (Exception ex) {
if (_log.shouldLog(Log.ERROR))

View File

@ -16,10 +16,10 @@ import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
import net.i2p.util.Clock;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorListener {
public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErrorListener {
private final static Log _log = new Log(I2PTunnelRunner.class);
private static volatile long __runnerId;
@ -125,7 +125,7 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
if (initialI2PData != null) {
synchronized (slock) {
i2pout.write(initialI2PData);
//i2pout.flush();
i2pout.flush();
}
}
if (initialSocketData != null) {
@ -222,7 +222,7 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
}
}
private class StreamForwarder extends I2PThread {
private class StreamForwarder extends I2PAppThread {
InputStream in;
OutputStream out;

View File

@ -4,6 +4,7 @@
package net.i2p.i2ptunnel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@ -24,7 +25,7 @@ import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.data.Base64;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
@ -48,26 +49,29 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
protected long readTimeout = DEFAULT_READ_TIMEOUT;
private static final boolean DEFAULT_USE_POOL = false;
protected static volatile long __serverId = 0;
private static final String PROP_HANDLER_COUNT = "i2ptunnel.blockingHandlerCount";
private static final int DEFAULT_HANDLER_COUNT = 10;
protected I2PTunnelTask task = null;
protected boolean bidir = false;
private int DEFAULT_LOCALPORT = 4488;
protected int localPort = DEFAULT_LOCALPORT;
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privData, notifyThis, tunnel);
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(privData));
String usePool = tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
SetUsePool(tunnel);
init(host, port, bais, privData, l);
}
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
String usePool = tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
SetUsePool(tunnel);
FileInputStream fis = null;
try {
fis = new FileInputStream(privkey);
@ -83,12 +87,17 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
String usePool = tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
SetUsePool(tunnel);
init(host, port, privData, privkeyname, l);
}
private void SetUsePool(I2PTunnel Tunnel) {
String usePool = Tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
init(host, port, privData, privkeyname, l);
}
private void init(InetAddress host, int port, InputStream privData, String privkeyname, Logging l) {
@ -106,17 +115,29 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
}
// copy the privData to a new BAIS, so we can always reset() it if we have to retry
ByteArrayInputStream privDataCopy;
try {
privDataCopy = copyOfInputStream(privData);
} catch (IOException ioe) {
_log.log(Log.CRIT, "Cannot read private key data for " + privkeyname, ioe);
return;
}
// Todo: Can't stop a tunnel from the UI while it's in this loop (no session yet)
while (sockMgr == null) {
synchronized (slock) {
sockMgr = I2PSocketManagerFactory.createManager(privData, getTunnel().host, portNum,
sockMgr = I2PSocketManagerFactory.createManager(privDataCopy, getTunnel().host, portNum,
props);
}
if (sockMgr == null) {
_log.log(Log.CRIT, "Unable to create socket manager");
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
privDataCopy.reset();
}
}
sockMgr.setName("Server");
getTunnel().addSession(sockMgr.getSession());
l.log("Ready!");
@ -124,15 +145,31 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
open = true;
}
private static volatile long __serverId = 0;
/**
* Copy input stream to a byte array, so we can retry
* @since 0.7.10
*/
private static ByteArrayInputStream copyOfInputStream(InputStream is) throws IOException {
byte[] buf = new byte[128];
ByteArrayOutputStream os = new ByteArrayOutputStream(768);
try {
int read;
while ((read = is.read(buf)) >= 0) {
os.write(buf, 0, read);
}
} finally {
try { is.close(); } catch (IOException ioe) {}
// don't need to close BAOS
}
return new ByteArrayInputStream(os.toByteArray());
}
/**
* Start running the I2PTunnelServer.
*
*/
public void startRunning() {
Thread t = new I2PThread(this);
Thread t = new I2PAppThread(this);
t.setName("Server " + (++__serverId));
t.start();
}
@ -158,6 +195,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
public boolean close(boolean forced) {
if (!open) return true;
if (task != null) {
task.close(forced);
}
synchronized (lock) {
if (!forced && sockMgr.listSockets().size() != 0) {
l.log("There are still active connections!");
@ -181,9 +221,6 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
}
private static final String PROP_HANDLER_COUNT = "i2ptunnel.blockingHandlerCount";
private static final int DEFAULT_HANDLER_COUNT = 10;
protected int getHandlerCount() {
int rv = DEFAULT_HANDLER_COUNT;
String cnt = getTunnel().getClientOptions().getProperty(PROP_HANDLER_COUNT);
@ -204,7 +241,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
int handlers = getHandlerCount();
for (int i = 0; i < handlers; i++) {
I2PThread handler = new I2PThread(new Handler(i2pS_S), "Handle Server " + i);
I2PAppThread handler = new I2PAppThread(new Handler(i2pS_S), "Handle Server " + i);
handler.start();
}
} else {
@ -213,7 +250,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
try {
final I2PSocket i2ps = i2pS_S.accept();
if (i2ps == null) throw new I2PException("I2PServerSocket closed");
new I2PThread(new Runnable() { public void run() { blockingHandle(i2ps); } }).start();
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);

View File

@ -14,7 +14,7 @@ import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
public class I2Ping extends I2PTunnelTask implements Runnable {
@ -59,7 +59,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
sockMgr = I2PTunnelClient.getSocketManager(tunnel);
}
}
Thread t = new I2PThread(this);
Thread t = new I2PAppThread(this);
t.setName("Client");
t.start();
open = true;
@ -188,7 +188,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
}
}
public class PingHandler extends I2PThread {
public class PingHandler extends I2PAppThread {
private String destination;
public PingHandler(String dest) {

View File

@ -0,0 +1,56 @@
package net.i2p.i2ptunnel;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import net.i2p.util.I2PAppThread;
import net.i2p.util.InternalServerSocket;
import net.i2p.util.Log;
/**
* Listen for in-JVM connections on the internal "socket"
*
* @author zzz
* @since 0.7.9
*/
class InternalSocketRunner implements Runnable {
private I2PTunnelClientBase client;
private int port;
private ServerSocket ss;
private boolean open;
private static final Log _log = new Log(InternalSocketRunner.class);
/** starts the runner */
InternalSocketRunner(I2PTunnelClientBase client) {
this.client = client;
this.port = client.getLocalPort();
Thread t = new I2PAppThread(this, "Internal socket port " + this.port, true);
t.start();
}
public final void run() {
try {
this.ss = new InternalServerSocket(this.port);
this.open = true;
while (true) {
Socket s = this.ss.accept();
this.client.manageConnection(s);
}
} catch (IOException ex) {
if (this.open) {
_log.error("Error listening for internal connections on " + this.port, ex);
}
this.open = false;
}
}
void stopRunning() {
if (this.open) {
try {
this.ss.close();
} catch (IOException ex) {}
this.open = false;
}
}
}

View File

@ -16,7 +16,7 @@ import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.data.Base32;
import net.i2p.data.Destination;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -106,7 +106,7 @@ public class TunnelController implements Logging {
public void startTunnelBackground() {
if (_running) return;
_starting = true;
new I2PThread(new Runnable() { public void run() { startTunnel(); } }).start();
new I2PAppThread(new Runnable() { public void run() { startTunnel(); } }).start();
}
/**
@ -154,6 +154,8 @@ public class TunnelController implements Logging {
startServer();
} else if ("httpserver".equals(type)) {
startHttpServer();
} else if ("httpbidirserver".equals(type)) {
startHttpBidirServer();
} else if ("ircserver".equals(type)) {
startIrcServer();
} else if ("streamrserver".equals(type)) {
@ -294,6 +296,16 @@ public class TunnelController implements Logging {
_tunnel.runHttpServer(new String[] { targetHost, targetPort, spoofedHost, privKeyFile }, this);
}
private void startHttpBidirServer() {
setListenOn();
String targetHost = getTargetHost();
String targetPort = getTargetPort();
String listenPort = getListenPort();
String spoofedHost = getSpoofedHost();
String privKeyFile = getPrivKeyFile();
_tunnel.runHttpBidirServer(new String[] { targetHost, targetPort, listenPort, spoofedHost, privKeyFile }, this);
}
private void startIrcServer() {
String targetHost = getTargetHost();
String targetPort = getTargetPort();

View File

@ -18,7 +18,7 @@ import net.i2p.I2PAppContext;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.data.DataHelper;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -94,7 +94,7 @@ public class TunnelControllerGroup {
_controllers.add(controller);
i++;
}
I2PThread startupThread = new I2PThread(new StartControllers(), "Startup tunnels");
I2PAppThread startupThread = new I2PAppThread(new StartControllers(), "Startup tunnels");
startupThread.start();
if (_log.shouldLog(Log.INFO))

View File

@ -55,7 +55,7 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
I2PSocket destSock = serv.getDestinationI2PSocket(this);
new I2PTunnelRunner(clientSock, destSock, sockLock, null, mySockets);
} catch (SOCKSException e) {
_log.error("Error from SOCKS connection: " + e.getMessage());
_log.error("Error from SOCKS connection", e);
closeSocket(s);
}
}

View File

@ -16,7 +16,7 @@ public class Pinger implements Source, Runnable {
public void start() {
this.running = true;
this.waitlock = new Object();
//this.waitlock = new Object();
this.thread.start();
}
@ -54,6 +54,6 @@ public class Pinger implements Source, Runnable {
protected Sink sink;
protected Thread thread;
protected Object waitlock; // FIXME should be final and use a factory. FIXME
private final Object waitlock = new Object();
protected boolean running;
}

View File

@ -29,7 +29,7 @@ public class I2PSink implements Sink {
// create maker
if (!raw)
this.maker = new I2PDatagramMaker(this.sess);
this.maker.setI2PDatagramMaker(this.sess);
}
/** @param src ignored */
@ -54,20 +54,8 @@ public class I2PSink implements Sink {
}
}
protected boolean raw;
protected I2PSession sess;
protected Destination dest;
protected I2PDatagramMaker maker; // FIXME should be final and use a factory. FIXME
protected final I2PDatagramMaker maker= new I2PDatagramMaker(); // FIXME should be final and use a factory. FIXME
}

View File

@ -28,7 +28,7 @@ public class I2PSinkAnywhere implements Sink {
// create maker
if (!raw)
this.maker = new I2PDatagramMaker(this.sess);
this.maker.setI2PDatagramMaker(this.sess);
}
/** @param to - where it's going */
@ -52,20 +52,8 @@ public class I2PSinkAnywhere implements Sink {
}
}
protected boolean raw;
protected I2PSession sess;
protected Destination dest;
protected I2PDatagramMaker maker; // FIXME should be final and use a factory. FIXME
protected final I2PDatagramMaker maker = new I2PDatagramMaker();
}

View File

@ -359,7 +359,7 @@ public class IndexBean {
if (tun != null && tun.getName() != null)
return tun.getName();
else
return "New Tunnel";
return _("New Tunnel");
}
public String getClientPort(int tunnel) {
@ -379,16 +379,17 @@ public class IndexBean {
}
public String getTypeName(String internalType) {
if ("client".equals(internalType)) return "Standard client";
else if ("httpclient".equals(internalType)) return "HTTP client";
else if ("ircclient".equals(internalType)) return "IRC client";
else if ("server".equals(internalType)) return "Standard server";
else if ("httpserver".equals(internalType)) return "HTTP server";
else if ("sockstunnel".equals(internalType)) return "SOCKS 4/4a/5 proxy";
else if ("connectclient".equals(internalType)) return "CONNECT/SSL/HTTPS proxy";
else if ("ircserver".equals(internalType)) return "IRC server";
else if ("streamrclient".equals(internalType)) return "Streamr client";
else if ("streamrserver".equals(internalType)) return "Streamr server";
if ("client".equals(internalType)) return _("Standard client");
else if ("httpclient".equals(internalType)) return _("HTTP client");
else if ("ircclient".equals(internalType)) return _("IRC client");
else if ("server".equals(internalType)) return _("Standard server");
else if ("httpserver".equals(internalType)) return _("HTTP server");
else if ("sockstunnel".equals(internalType)) return _("SOCKS 4/4a/5 proxy");
else if ("connectclient".equals(internalType)) return _("CONNECT/SSL/HTTPS proxy");
else if ("ircserver".equals(internalType)) return _("IRC server");
else if ("streamrclient".equals(internalType)) return _("Streamr client");
else if ("streamrserver".equals(internalType)) return _("Streamr server");
else if ("httpbidirserver".equals(internalType)) return _("HTTP bidir");
else return internalType;
}
@ -779,8 +780,11 @@ public class IndexBean {
config.setProperty("listenPort", _port);
if (_reachableByOther != null)
config.setProperty("interface", _reachableByOther);
else
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));
@ -806,11 +810,22 @@ public class IndexBean {
} else if ("ircclient".equals(_type) || "client".equals(_type) || "streamrclient".equals(_type)) {
if (_targetDestination != null)
config.setProperty("targetDestination", _targetDestination);
} else if ("httpserver".equals(_type)) {
} else if ("httpserver".equals(_type) || "httpbidirserver".equals(_type)) {
if (_spoofedHost != null)
config.setProperty("spoofedHost", _spoofedHost);
}
if ("httpbidirserver".equals(_type)) {
if (_port != null)
config.setProperty("listenPort", _port);
if (_reachableByOther != null)
config.setProperty("interface", _reachableByOther);
else if (_reachableBy != null)
config.setProperty("interface", _reachableBy);
else if (_targetHost != null)
config.setProperty("interface", _targetHost);
else
config.setProperty("interface", "");
}
return config;
}
@ -935,4 +950,8 @@ public class IndexBean {
buf.append((String)msgs.get(i)).append("\n");
}
}
private String _(String key) {
return Messages._(key, _context);
}
}

View File

@ -0,0 +1,42 @@
package net.i2p.i2ptunnel.web;
import net.i2p.I2PAppContext;
import net.i2p.util.Translate;
/**
* Translate strings for this package.
* @since 0.7.9
*/
public class Messages {
private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
private final I2PAppContext _context;
public Messages() {
_context = I2PAppContext.getGlobalContext();
}
/** lang in routerconsole.lang property, else current locale */
public String _(String key) {
return Translate.getString(key, _context, BUNDLE_NAME);
}
public static String _(String key, I2PAppContext ctx) {
return Translate.getString(key, ctx, BUNDLE_NAME);
}
/**
* translate a string with a parameter
* This is a lot more expensive than getString(s, ctx), so use sparingly.
*
* @param s string to be translated containing {0}
* The {0} will be replaced by the parameter.
* Single quotes must be doubled, i.e. ' -> '' in the string.
* @param o parameter, not translated.
* To tranlslate parameter also, use _("foo {0} bar", _("baz"))
* Do not double the single quotes in the parameter.
* Use autoboxing to call with ints, longs, floats, etc.
*/
public String _(String s, Object o) {
return Translate.getString(s, o, _context, BUNDLE_NAME);
}
}

View File

@ -1,6 +1,7 @@
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"%><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
<jsp:useBean class="net.i2p.i2ptunnel.web.Messages" id="intl" scope="request" />
<% String tun = request.getParameter("tunnel");
int curTunnel = -1;
if (tun != null) {
@ -13,7 +14,7 @@
%>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>I2P Tunnel Manager - Edit</title>
<title><%=intl._("I2P Tunnel Manager - Edit Client Tunnel")%></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
@ -38,11 +39,11 @@
if (curTunnel >= 0) {
tunnelTypeName = editBean.getTunnelType(curTunnel);
tunnelType = editBean.getInternalType(curTunnel);
%><h4>Edit proxy settings</h4><%
%><h4><%=intl._("Edit proxy settings")%></h4><%
} else {
tunnelTypeName = editBean.getTypeName(request.getParameter("type"));
tunnelType = request.getParameter("type");
%><h4>New proxy settings</h4><%
%><h4><%=intl._("New proxy settings")%></h4><%
} %>
<input type="hidden" name="tunnel" value="<%=request.getParameter("tunnel")%>" />
<input type="hidden" name="nonce" value="<%=editBean.getNextNonce()%>" />
@ -55,17 +56,17 @@
<div id="nameField" class="rowItem">
<label for="name" accesskey="N">
<span class="accessKey">N</span>ame:
<%=intl._("Name")%>:(<span class="accessKey">N</span>)
</label>
<input type="text" size="30" maxlength="50" name="name" id="name" title="Tunnel Name" value="<%=editBean.getTunnelName(curTunnel)%>" class="freetext" />
</div>
<div id="typeField" class="rowItem">
<label>Type:</label>
<label><%=intl._("Type")%>:</label>
<span class="text"><%=tunnelTypeName%></span>
</div>
<div id="descriptionField" class="rowItem">
<label for="description" accesskey="e">
D<span class="accessKey">e</span>scription:
<%=intl._("Description")%>:(<span class="accessKey">E</span>)
</label>
<input type="text" size="60" maxlength="80" name="description" id="description" title="Tunnel Description" value="<%=editBean.getTunnelDescription(curTunnel)%>" class="freetext" />
</div>
@ -76,17 +77,20 @@
<div id="accessField" class="rowItem">
<% if ("streamrclient".equals(tunnelType)) { %>
<label>Target:</label>
<label><%=intl._("Target")%>:</label>
<% } else { %>
<label>Access Point:</label>
<label><%=intl._("Access Point")%>:</label>
<% } %>
</div>
<div id="portField" class="rowItem">
<label for="port" accesskey="P">
<span class="accessKey">P</span>ort:
<% String value = editBean.getClientPort(curTunnel);
if (value == null || "".equals(value.trim()))
out.write(" <font color=\"red\">(required)</font>");
if (value == null || "".equals(value.trim())) {
out.write(" <font color=\"red\">(");
out.write(intl._("required"));
out.write(")</font>");
}
%>
</label>
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
@ -98,7 +102,7 @@
} else { %>
<div id="reachField" class="rowItem">
<label for="reachableBy" accesskey="r">
<span class="accessKey">R</span>eachable by:
<%=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)) &&
@ -107,9 +111,9 @@
(clientInterface.trim().length() > 0)) {
otherInterface = clientInterface;
}
%><option value="127.0.0.1"<%=("127.0.0.1".equals(clientInterface) ? " selected=\"selected\"" : "")%>>Locally (127.0.0.1)</option>
<option value="0.0.0.0"<%=("0.0.0.0".equals(clientInterface) ? " selected=\"selected\"" : "")%>>Everyone (0.0.0.0)</option>
<option value="other"<%=(!("".equals(otherInterface)) ? " selected=\"selected\"" : "")%>>LAN Hosts (Please specify your LAN address)</option>
%><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 %>
@ -118,11 +122,14 @@
<% if ("streamrclient".equals(tunnelType)) { %>
Host:
<% String vvv = otherInterface;
if (vvv == null || "".equals(vvv.trim()))
out.write(" <font color=\"red\">(required)</font>");
if (vvv == null || "".equals(vvv.trim())) {
out.write(" <font color=\"red\">(");
out.write(intl._("required"));
out.write(")</font>");
}
%>
<% } else { %>
<span class="accessKey">O</span>ther:
<%=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" />
@ -135,55 +142,58 @@
<% if ("httpclient".equals(tunnelType) || "connectclient".equals(tunnelType)) {
%><div id="destinationField" class="rowItem">
<label for="proxyList" accesskey="x">
Outpro<span class="accessKey">x</span>ies:
<%=intl._("Outproxies")%>(<span class="accessKey">x</span>):
</label>
<input type="text" size="30" id="proxyList" name="proxyList" title="List of Outproxy I2P destinations" value="<%=editBean.getClientDestination(curTunnel)%>" class="freetext" />
</div>
<% } else if ("client".equals(tunnelType) || "ircclient".equals(tunnelType) || "streamrclient".equals(tunnelType)) {
%><div id="destinationField" class="rowItem">
<label for="targetDestination" accesskey="T">
<span class="accessKey">T</span>unnel Destination:
<%=intl._("Tunnel Destination")%>(<span class="accessKey">T</span>):
<% String value2 = editBean.getClientDestination(curTunnel);
if (value2 == null || "".equals(value2.trim()))
out.write(" <font color=\"red\">(required)</font>");
if (value2 == null || "".equals(value2.trim())) {
out.write(" <font color=\"red\">(");
out.write(intl._("required"));
out.write(")</font>");
}
%>
</label>
<input type="text" size="30" id="targetDestination" name="targetDestination" title="Destination of the Tunnel" value="<%=editBean.getClientDestination(curTunnel)%>" class="freetext" />
<span class="comment">(name or destination)</span>
<span class="comment">(<%=intl._("name or destination")%>)</span>
</div>
<% } %>
<% if (!"streamrclient".equals(tunnelType)) { %>
<div id="profileField" class="rowItem">
<label for="profile" accesskey="f">
Pro<span class="accessKey">f</span>ile:
<%=intl._("Profile")%>(<span class="accessKey">f</span>):
</label>
<select id="profile" name="profile" title="Connection Profile" class="selectbox">
<% boolean interactiveProfile = editBean.isInteractive(curTunnel);
%><option <%=(interactiveProfile == true ? "selected=\"selected\" " : "")%>value="interactive">interactive connection </option>
<option <%=(interactiveProfile == false ? "selected=\"selected\" " : "")%>value="bulk">bulk connection (downloads/websites/BT) </option>
%><option <%=(interactiveProfile == true ? "selected=\"selected\" " : "")%>value="interactive"><%=intl._("interactive connection")%> </option>
<option <%=(interactiveProfile == false ? "selected=\"selected\" " : "")%>value="bulk"><%=intl._("bulk connection (downloads/websites/BT)")%> </option>
</select>
</div>
<div id="delayConnectField" class="rowItem">
<label for="connectDelay" accesskey="y">
Dela<span class="accessKey">y</span> Connect:
<%=intl._("Delay Connect")%>(<span class="accessKey">y</span>):
</label>
<input value="1000" type="checkbox" id="connectDelay" name="connectDelay" title="Delay Connection"<%=(editBean.shouldDelay(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<span class="comment">(for request/response connections)</span>
<span class="comment">(<%=intl._("for request/response connections")%>)</span>
</div>
<div id="sharedtField" class="rowItem">
<label for="shared" accesskey="h">
S<span class="accessKey">h</span>ared Client:
<%=intl._("Shared Client")%>(<span class="accessKey">h</span>):
</label>
<input value="true" type="checkbox" id="shared" name="shared" title="Share tunnels with other clients"<%=(editBean.isSharedClient(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<span class="comment">(Share tunnels with other clients and irc/httpclients? Change requires restart of client proxy)</span>
<span class="comment"><%=intl._("(Share tunnels with other clients and irc/httpclients? Change requires restart of client proxy)")%></span>
</div>
<% } // !streamrclient %>
<div id="startupField" class="rowItem">
<label for="startOnLoad" accesskey="a">
<span class="accessKey">A</span>uto Start:
<%=intl._("Auto Start")%>(<span class="accessKey">A</span>):
</label>
<input value="1" type="checkbox" id="startOnLoad" name="startOnLoad" title="Start Tunnel Automatically"<%=(editBean.startAutomatically(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<span class="comment">(Check the Box for 'YES')</span>
<span class="comment"><%=intl._("(Check the Box for 'YES')")%></span>
</div>
<div class="footer">
@ -192,8 +202,8 @@
<div id="tunnelAdvancedNetworking" class="panel">
<div class="header">
<h4>Advanced networking options</h4><br />
<span class="comment">(NOTE: when this client proxy is configured to share tunnels, then these options are for all the shared proxy clients!)</span>
<h4><%=intl._("Advanced networking options")%></h4><br />
<span class="comment"><%=intl._("(NOTE: when this client proxy is configured to share tunnels, then these options are for all the shared proxy clients!)")%></span>
</div>
<div class="separator">
@ -201,65 +211,65 @@
</div>
<div id="tunnelOptionsField" class="rowItem">
<label>Tunnel Options:</label>
<label><%=intl._("Tunnel Options")%>:</label>
</div>
<div id="depthField" class="rowItem">
<label for="tunnelDepth" accesskey="t">
Dep<span class="accessKey">t</span>h:
<%=intl._("Length")%>(<span class="accessKey">t</span>):
</label>
<select id="tunnelDepth" name="tunnelDepth" title="Depth of each Tunnel" class="selectbox">
<select id="tunnelDepth" name="tunnelDepth" title="Length of each Tunnel" class="selectbox">
<% int tunnelDepth = editBean.getTunnelDepth(curTunnel, 2);
%><option value="0"<%=(tunnelDepth == 0 ? " selected=\"selected\"" : "") %>>0 hop tunnel (low anonymity, low latency)</option>
<option value="1"<%=(tunnelDepth == 1 ? " selected=\"selected\"" : "") %>>1 hop tunnel (medium anonymity, medium latency)</option>
<option value="2"<%=(tunnelDepth == 2 ? " selected=\"selected\"" : "") %>>2 hop tunnel (high anonymity, high latency)</option>
<option value="3"<%=(tunnelDepth == 3 ? " selected=\"selected\"" : "") %>>3 hop tunnel (very high anonymity, poor performance)</option>
%><option value="0"<%=(tunnelDepth == 0 ? " selected=\"selected\"" : "") %>><%=intl._("0 hop tunnel (low anonymity, low latency)")%></option>
<option value="1"<%=(tunnelDepth == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 hop tunnel (medium anonymity, medium latency)")%></option>
<option value="2"<%=(tunnelDepth == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 hop tunnel (high anonymity, high latency)")%></option>
<option value="3"<%=(tunnelDepth == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 hop tunnel (very high anonymity, poor performance)")%></option>
<% if (tunnelDepth > 3) {
%> <option value="<%=tunnelDepth%>" selected="selected"><%=tunnelDepth%> hop tunnel (very poor performance)</option>
%> <option value="<%=tunnelDepth%>" selected="selected"><%=tunnelDepth%> <%=intl._("hop tunnel (very poor performance)")%></option>
<% }
%></select>
</div>
<div id="varianceField" class="rowItem">
<label for="tunnelVariance" accesskey="v">
<span class="accessKey">V</span>ariance:
<%=intl._("Variance")%>(<span class="accessKey">V</span>):
</label>
<select id="tunnelVariance" name="tunnelVariance" title="Level of Randomization for Tunnel Depth" class="selectbox">
<select id="tunnelVariance" name="tunnelVariance" title="Level of Randomization for Tunnel Length" class="selectbox">
<% int tunnelVariance = editBean.getTunnelVariance(curTunnel, 0);
%><option value="0"<%=(tunnelVariance == 0 ? " selected=\"selected\"" : "") %>>0 hop variance (no randomisation, consistant performance)</option>
<option value="1"<%=(tunnelVariance == 1 ? " selected=\"selected\"" : "") %>>+ 0-1 hop variance (medium additive randomisation, subtractive performance)</option>
<option value="2"<%=(tunnelVariance == 2 ? " selected=\"selected\"" : "") %>>+ 0-2 hop variance (high additive randomisation, subtractive performance)</option>
<option value="-1"<%=(tunnelVariance == -1 ? " selected=\"selected\"" : "") %>>+/- 0-1 hop variance (standard randomisation, standard performance)</option>
<option value="-2"<%=(tunnelVariance == -2 ? " selected=\"selected\"" : "") %>>+/- 0-2 hop variance (not recommended)</option>
%><option value="0"<%=(tunnelVariance == 0 ? " selected=\"selected\"" : "") %>><%=intl._("0 hop variance (no randomisation, consistant performance)")%></option>
<option value="1"<%=(tunnelVariance == 1 ? " selected=\"selected\"" : "") %>><%=intl._("+ 0-1 hop variance (medium additive randomisation, subtractive performance)")%></option>
<option value="2"<%=(tunnelVariance == 2 ? " selected=\"selected\"" : "") %>><%=intl._("+ 0-2 hop variance (high additive randomisation, subtractive performance)")%></option>
<option value="-1"<%=(tunnelVariance == -1 ? " selected=\"selected\"" : "") %>><%=intl._("+/- 0-1 hop variance (standard randomisation, standard performance)")%></option>
<option value="-2"<%=(tunnelVariance == -2 ? " selected=\"selected\"" : "") %>><%=intl._("+/- 0-2 hop variance (not recommended)")%></option>
<% if (tunnelVariance > 2 || tunnelVariance < -2) {
%> <option value="<%=tunnelVariance%>" selected="selected"><%= (tunnelVariance > 2 ? "+ " : "+/- ") %>0-<%=tunnelVariance%> hop variance</option>
%> <option value="<%=tunnelVariance%>" selected="selected"><%= (tunnelVariance > 2 ? "+ " : "+/- ") %>0-<%=tunnelVariance%> <%=intl._("hop variance")%></option>
<% }
%></select>
</div>
<div id="countField" class="rowItem">
<label for="tunnelQuantity" accesskey="C">
<span class="accessKey">C</span>ount:
<%=intl._("Count")%>(<span class="accessKey">C</span>):
</label>
<select id="tunnelQuantity" name="tunnelQuantity" title="Number of Tunnels in Group" class="selectbox">
<% int tunnelQuantity = editBean.getTunnelQuantity(curTunnel, 2);
%><option value="1"<%=(tunnelQuantity == 1 ? " selected=\"selected\"" : "") %>>1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)</option>
<option value="2"<%=(tunnelQuantity == 2 ? " selected=\"selected\"" : "") %>>2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)</option>
<option value="3"<%=(tunnelQuantity == 3 ? " selected=\"selected\"" : "") %>>3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)</option>
%><option value="1"<%=(tunnelQuantity == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)")%></option>
<option value="2"<%=(tunnelQuantity == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)")%></option>
<option value="3"<%=(tunnelQuantity == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)")%></option>
<% if (tunnelQuantity > 3) {
%> <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> tunnels</option>
%> <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> <%=intl._("tunnels")%></option>
<% }
%></select>
</div>
<div id="backupField" class="rowItem">
<label for="tunnelBackupQuantity" accesskey="b">
<span class="accessKey">B</span>ackup Count:
<%=intl._("Backup Count")%>(<span class="accessKey">B</span>):
</label>
<select id="tunnelBackupQuantity" name="tunnelBackupQuantity" title="Number of Reserve Tunnels" class="selectbox">
<% int tunnelBackupQuantity = editBean.getTunnelBackupQuantity(curTunnel, 0);
%><option value="0"<%=(tunnelBackupQuantity == 0 ? " selected=\"selected\"" : "") %>>0 backup tunnels (0 redundancy, no added resource usage)</option>
<option value="1"<%=(tunnelBackupQuantity == 1 ? " selected=\"selected\"" : "") %>>1 backup tunnel each direction (low redundancy, low resource usage)</option>
<option value="2"<%=(tunnelBackupQuantity == 2 ? " selected=\"selected\"" : "") %>>2 backup tunnels each direction (medium redundancy, medium resource usage)</option>
<option value="3"<%=(tunnelBackupQuantity == 3 ? " selected=\"selected\"" : "") %>>3 backup tunnels each direction (high redundancy, high resource usage)</option>
%><option value="0"<%=(tunnelBackupQuantity == 0 ? " selected=\"selected\"" : "") %>><%=intl._("0 backup tunnels (0 redundancy, no added resource usage)")%></option>
<option value="1"<%=(tunnelBackupQuantity == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 backup tunnel each direction (low redundancy, low resource usage)")%></option>
<option value="2"<%=(tunnelBackupQuantity == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 backup tunnels each direction (medium redundancy, medium resource usage)")%></option>
<option value="3"<%=(tunnelBackupQuantity == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 backup tunnels each direction (high redundancy, high resource usage)")%></option>
<% if (tunnelBackupQuantity > 3) {
%> <option value="<%=tunnelBackupQuantity%>" selected="selected"><%=tunnelBackupQuantity%> backup tunnels</option>
%> <option value="<%=tunnelBackupQuantity%>" selected="selected"><%=tunnelBackupQuantity%> <%=intl._("backup tunnels")%></option>
<% }
%></select>
</div>
@ -269,17 +279,17 @@
</div>
<div id="optionsField" class="rowItem">
<label>I2CP Options:</label>
<label><%=intl._("I2CP Options")%>:</label>
</div>
<div id="optionsHostField" class="rowItem">
<label for="clientHost" accesskey="o">
H<span class="accessKey">o</span>st:
<%=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" />
</div>
<div id="optionsPortField" class="rowItem">
<label for="clientPort" accesskey="r">
Po<span class="accessKey">r</span>t:
<%=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" />
</div>
@ -291,24 +301,24 @@
<div id="optionsField" class="rowItem">
<label for="reduce" accesskey="d">
Re<span class="accessKey">d</span>uce tunnel quantity when idle:
<%=intl._("Reduce tunnel quantity when idle")%>(<span class="accessKey">d</span>):
</label>
</div>
<div id="portField" class="rowItem">
<label for="access" accesskey="d">
Enable:
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="reduce" title="Reduce Tunnels"<%=(editBean.getReduce(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="portField" class="rowItem">
<label for="reduceCount" accesskey="d">
Reduced tunnel count:
<%=intl._("Reduced tunnel count")%>:
</label>
<input type="text" id="port" name="reduceCount" size="1" maxlength="1" title="Reduced Tunnel Count" value="<%=editBean.getReduceCount(curTunnel)%>" class="freetext" />
</div>
<div id="portField" class="rowItem">
<label for="reduceTime" accesskey="d">
Idle minutes:
<%=intl._("Idle minutes")%>:
</label>
<input type="text" id="port" name="reduceTime" size="4" maxlength="4" title="Reduced Tunnel Idle Time" value="<%=editBean.getReduceTime(curTunnel)%>" class="freetext" />
</div>
@ -319,31 +329,31 @@
<div id="optionsField" class="rowItem">
<label for="reduce" accesskey="c">
<span class="accessKey">C</span>lose tunnels when idle:
<%=intl._("Close tunnels when idle")%>(<span class="accessKey">C</span>):
</label>
</div>
<div id="portField" class="rowItem">
<label for="access" accesskey="c">
Enable:
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="close" title="Close Tunnels"<%=(editBean.getClose(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="portField" class="rowItem">
<label for="access" accesskey="c">
New Keys on Reopen:
<%=intl._("New Keys on Reopen")%>:
</label>
<table border="0"><tr><!-- I give up -->
<td><input value="1" type="radio" id="startOnLoad" name="newDest" title="New Destination"
<%=(editBean.getNewDest(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<td>Enable
<td><%=intl._("Enable")%>
<td><input value="0" type="radio" id="startOnLoad" name="newDest" title="New Destination"
<%=(editBean.getNewDest(curTunnel) || editBean.getPersistentClientKey(curTunnel) ? "" : " checked=\"checked\"")%> class="tickbox" />
<td>Disable
<td><%=intl._("Disable")%>
</table>
</div>
<div id="portField" class="rowItem">
<label for="reduceTime" accesskey="c">
Idle minutes:
<%=intl._("Idle minutes")%>:
</label>
<input type="text" id="port" name="closeTime" size="4" maxlength="4" title="Close Tunnel Idle Time" value="<%=editBean.getCloseTime(curTunnel)%>" class="freetext" />
</div>
@ -354,12 +364,12 @@
<div id="optionsField" class="rowItem">
<label for="reduce" accesskey="c">
<span class="accessKey">D</span>elay tunnel open until required:
<%=intl._("Delay tunnel open until required")%>(<span class="accessKey">D</span>):
</label>
</div>
<div id="portField" class="rowItem">
<label for="access" accesskey="c">
Enable:
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="delayOpen" title="Delay Tunnel Open"<%=(editBean.getDelayOpen(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
@ -372,24 +382,24 @@
<% if ("client".equals(tunnelType) || "ircclient".equals(tunnelType)) { %>
<div id="optionsField" class="rowItem">
<label for="privKeyFile" accesskey="k">
Persistent private <span class="accessKey">k</span>ey:
<%=intl._("Persistent private key")%>(<span class="accessKey">k</span>):
</label>
</div>
<div id="portField" class="rowItem">
<label>Enable:</label>
<label><%=intl._("Enable")%>:</label>
<input value="2" type="radio" id="startOnLoad" name="newDest" title="New Destination"
<%=(editBean.getPersistentClientKey(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="reachField" class="rowItem">
<label>File:</label>
<label><%=intl._("File")%>:</label>
<input type="text" size="30" id="clientHost" name="privKeyFile" title="Path to Private Key File" value="<%=editBean.getPrivateKeyFile(curTunnel)%>" class="freetext" />
</div>
<div id="destinationField" class="rowItem">
<label for="localDestination" accesskey="L">
<span class="accessKey">L</span>ocal destination:
<%=intl._("Local destination")%>(<span class="accessKey">L</span>):
</label>
<textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" wrap="off"><%=editBean.getDestinationBase64(curTunnel)%></textarea>
<span class="comment">(if known)</span>
<span class="comment"><%=intl._("(if known)")%></span>
</div>
<div class="subdivider">
@ -399,7 +409,7 @@
<div id="customOptionsField" class="rowItem">
<label for="customOptions" accesskey="u">
C<span class="accessKey">u</span>stom options:
<%=intl._("Custom options")%>(<span class="accessKey">u</span>):
</label>
<input type="text" id="customOptions" name="customOptions" size="60" title="Custom Options" value="<%=editBean.getCustomOptions(curTunnel)%>" class="freetext" />
</div>
@ -411,12 +421,12 @@
<div class="header"></div>
<div class="footer">
<div class="toolbox">
<span class="comment">NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted.</span>
<span class="comment"><%=intl._("NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted.")%></span>
<div class="separator"><hr /></div>
<input type="hidden" value="true" name="removeConfirm" />
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Save changes" title="Save Changes"><span class="accessKey">S</span>ave</button>
<button id="controlDelete" <%=(editBean.allowJS() ? "onclick=\"if (!confirm('Are you sure you want to delete?')) { return false; }\" " : "")%>accesskey="D" class="control" type="submit" name="action" value="Delete this proxy" title="Delete this Proxy"><span class="accessKey">D</span>elete</button>
<button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel">Cancel</button>
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Save changes" title="Save Changes"><%=intl._("Save")%>(<span class="accessKey">S</span>)</button>
<button id="controlDelete" <%=(editBean.allowJS() ? "onclick=\"if (!confirm('Are you sure you want to delete?')) { return false; }\" " : "")%>accesskey="D" class="control" type="submit" name="action" value="Delete this proxy" title="Delete this Proxy"><%=intl._("Delete")%>(<span class="accessKey">D</span>)</button>
<button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel"><%=intl._("Cancel")%></button>
</div>
</div>
</div>

View File

@ -1,6 +1,7 @@
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"%><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
<jsp:useBean class="net.i2p.i2ptunnel.web.Messages" id="intl" scope="request" />
<% String tun = request.getParameter("tunnel");
int curTunnel = -1;
if (tun != null) {
@ -13,7 +14,7 @@
%>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>I2P Tunnel Manager - Edit</title>
<title><%=intl._("I2P Tunnel Manager - Edit Server Tunnel")%></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
@ -38,11 +39,11 @@
if (curTunnel >= 0) {
tunnelTypeName = editBean.getTunnelType(curTunnel);
tunnelType = editBean.getInternalType(curTunnel);
%><h4>Edit server settings</h4><%
%><h4><%=intl._("Edit server settings")%></h4><%
} else {
tunnelTypeName = editBean.getTypeName(request.getParameter("type"));
tunnelType = request.getParameter("type");
%><h4>New server settings</h4><%
%><h4><%=intl._("New server settings")%></h4><%
} %>
<input type="hidden" name="tunnel" value="<%=request.getParameter("tunnel")%>" />
<input type="hidden" name="nonce" value="<%=editBean.getNextNonce()%>" />
@ -55,26 +56,26 @@
<div id="nameField" class="rowItem">
<label for="name" accesskey="N">
<span class="accessKey">N</span>ame:
<%=intl._("Name")%>(<span class="accessKey">N</span>):
</label>
<input type="text" size="30" maxlength="50" name="name" id="name" title="Tunnel Name" value="<%=editBean.getTunnelName(curTunnel)%>" class="freetext" />
</div>
<div id="typeField" class="rowItem">
<label>Type:</label>
<label><%=intl._("Type")%>:</label>
<span class="text"><%=tunnelTypeName%></span>
</div>
<div id="descriptionField" class="rowItem">
<label for="description" accesskey="e">
D<span class="accessKey">e</span>scription:
<%=intl._("Description")%>(<span class="accessKey">e</span>):
</label>
<input type="text" size="60" maxlength="80" name="description" id="description" title="Tunnel Description" value="<%=editBean.getTunnelDescription(curTunnel)%>" class="freetext" />
</div>
<div id="startupField" class="rowItem">
<label for="startOnLoad" accesskey="a">
<span class="accessKey">A</span>uto Start:
<%=intl._("Auto Start")%>(<span class="accessKey">A</span>):
</label>
<input value="1" type="checkbox" id="startOnLoad" name="startOnLoad" title="Start Tunnel Automatically"<%=(editBean.startAutomatically(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<span class="comment">(Check the Box for 'YES')</span>
<span class="comment"><%=intl._("(Check the Box for 'YES')")%></span>
</div>
<div class="subdivider">
@ -83,74 +84,128 @@
<div id="targetField" class="rowItem">
<% if ("streamrserver".equals(tunnelType)) { %>
<label>Access Point:</label>
<label><%=intl._("Access Point")%>:</label>
<% } else { %>
<label>Target:</label>
<label><%=intl._("Target")%>:</label>
<% } %>
</div>
<div id="hostField" class="rowItem">
<label for="targetHost" accesskey="H">
<% if ("streamrserver".equals(tunnelType)) { %>
<span class="accessKey">R</span>eachable by:
<%=intl._("Reachable by")%>(<span class="accessKey">R</span>):
<% } else { %>
<span class="accessKey">H</span>ost:
<%=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>
<div id="portField" class="rowItem">
<label for="targetPort" accesskey="P">
<span class="accessKey">P</span>ort:
<%=intl._("Port")%>(<span class="accessKey">P</span>):
<% String value = editBean.getTargetPort(curTunnel);
if (value == null || "".equals(value.trim()))
out.write(" <font color=\"red\">(required)</font>");
if (value == null || "".equals(value.trim())) {
out.write(" <font color=\"red\">(");
out.write(intl._("required"));
out.write(")</font>");
}
%>
</label>
<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)) {
%>
<div class="subdivider">
<hr />
</div>
<div id="accessField" class="rowItem">
<label><%=intl._("Access Point")%>:</label>
</div>
<div id="portField" class="rowItem">
<label for="port" accesskey="P">
<span class="accessKey">P</span>ort:
<% String value4 = editBean.getClientPort(curTunnel);
if (value4 == null || "".equals(value4.trim())) {
out.write(" <font color=\"red\">(");
out.write(intl._("required"));
out.write(")</font>");
}
%>
</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);
%>
<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>
<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>
<% } %>
<div class="subdivider">
<hr />
</div>
<% if ("httpserver".equals(tunnelType)) {
<% if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
%><div id="websiteField" class="rowItem">
<label for="spoofedHost" accesskey="W">
<span class="accessKey">W</span>ebsite name:
<%=intl._("Website name")%>(<span class="accessKey">W</span>):
</label>
<input type="text" size="20" id="targetHost" name="spoofedHost" title="Website Host Name" value="<%=editBean.getSpoofedHost(curTunnel)%>" class="freetext" />
<span class="comment">(leave blank for outproxies)</span>
<span class="comment"><%=intl._("(leave blank for outproxies)")%></span>
</div>
<% }
%><div id="privKeyField" class="rowItem">
<label for="privKeyFile" accesskey="k">
Private <span class="accessKey">k</span>ey file:
<% String value2 = editBean.getPrivateKeyFile(curTunnel);
if (value2 == null || "".equals(value2.trim()))
out.write(" <font color=\"red\">(required)</font>");
<%=intl._("Private key file")%>(<span class="accessKey">k</span>):
<% String value3 = editBean.getPrivateKeyFile(curTunnel);
if (value3 == null || "".equals(value3.trim())) {
out.write(" <font color=\"red\">(");
out.write(intl._("required"));
out.write(")</font>");
}
%>
</label>
<input type="text" size="30" id="privKeyFile" name="privKeyFile" title="Path to Private Key File" value="<%=editBean.getPrivateKeyFile(curTunnel)%>" class="freetext" />
</div>
<% if (!"streamrserver".equals(tunnelType)) { %>
<div id="profileField" class="rowItem">
<label for="profile" accesskey="f">
Pro<span class="accessKey">f</span>ile:
<%=intl._("Profile")%>(<span class="accessKey">f</span>):
</label>
<select id="profile" name="profile" title="Connection Profile" class="selectbox">
<% boolean interactiveProfile = editBean.isInteractive(curTunnel);
%><option <%=(interactiveProfile == true ? "selected=\"selected\" " : "")%>value="interactive">interactive connection </option>
<option <%=(interactiveProfile == false ? "selected=\"selected\" " : "")%>value="bulk">bulk connection (downloads/websites/BT) </option>
%><option <%=(interactiveProfile == true ? "selected=\"selected\" " : "")%>value="interactive"><%=intl._("interactive connection")%> </option>
<option <%=(interactiveProfile == false ? "selected=\"selected\" " : "")%>value="bulk"><%=intl._("bulk connection (downloads/websites/BT)")%> </option>
</select>
</div>
<% } // !streamrserver %>
<div id="destinationField" class="rowItem">
<label for="localDestination" accesskey="L">
<span class="accessKey">L</span>ocal destination:
<%=intl._("Local destination")%>(<span class="accessKey">L</span>):
</label>
<textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" wrap="off"><%=editBean.getDestinationBase64(curTunnel)%></textarea>
<% if (!"".equals(editBean.getDestinationBase64(curTunnel))) { %>
<a href="/susidns/addressbook.jsp?book=private&hostname=<%=editBean.getTunnelName(curTunnel)%>&destination=<%=editBean.getDestinationBase64(curTunnel)%>#add">Add to local addressbook</a>
<a href="/susidns/addressbook.jsp?book=private&hostname=<%=editBean.getTunnelName(curTunnel)%>&destination=<%=editBean.getDestinationBase64(curTunnel)%>#add"><%=intl._("Add to local addressbook")%></a>
<% } %>
</div>
@ -160,7 +215,7 @@
<div id="tunnelAdvancedNetworking" class="panel">
<div class="header">
<h4>Advanced networking options</h4>
<h4><%=intl._("Advanced networking options")%></h4>
</div>
<div class="separator">
@ -168,65 +223,65 @@
</div>
<div id="tunnelOptionsField" class="rowItem">
<label>Tunnel Options:</label>
<label><%=intl._("Tunnel Options")%>:</label>
</div>
<div id="depthField" class="rowItem">
<label for="tunnelDepth" accesskey="t">
Dep<span class="accessKey">t</span>h:
<%=intl._("Length")%>(<span class="accessKey">t</span>):
</label>
<select id="tunnelDepth" name="tunnelDepth" title="Depth of each Tunnel" class="selectbox">
<select id="tunnelDepth" name="tunnelDepth" title="Length of each Tunnel" class="selectbox">
<% int tunnelDepth = editBean.getTunnelDepth(curTunnel, 2);
%><option value="0"<%=(tunnelDepth == 0 ? " selected=\"selected\"" : "") %>>0 hop tunnel (low anonymity, low latency)</option>
<option value="1"<%=(tunnelDepth == 1 ? " selected=\"selected\"" : "") %>>1 hop tunnel (medium anonymity, medium latency)</option>
<option value="2"<%=(tunnelDepth == 2 ? " selected=\"selected\"" : "") %>>2 hop tunnel (high anonymity, high latency)</option>
<option value="3"<%=(tunnelDepth == 3 ? " selected=\"selected\"" : "") %>>3 hop tunnel (very high anonymity, poor performance)</option>
%><option value="0"<%=(tunnelDepth == 0 ? " selected=\"selected\"" : "") %>><%=intl._("0 hop tunnel (low anonymity, low latency)")%></option>
<option value="1"<%=(tunnelDepth == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 hop tunnel (medium anonymity, medium latency)")%></option>
<option value="2"<%=(tunnelDepth == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 hop tunnel (high anonymity, high latency)")%></option>
<option value="3"<%=(tunnelDepth == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 hop tunnel (very high anonymity, poor performance)")%></option>
<% if (tunnelDepth > 3) {
%> <option value="<%=tunnelDepth%>" selected="selected"><%=tunnelDepth%> hop tunnel (very poor performance)</option>
%> <option value="<%=tunnelDepth%>" selected="selected"><%=tunnelDepth%> <%=intl._("hop tunnel (very poor performance)")%></option>
<% }
%></select>
</div>
<div id="varianceField" class="rowItem">
<label for="tunnelVariance" accesskey="v">
<span class="accessKey">V</span>ariance:
<%=intl._("Variance")%>(<span class="accessKey">V</span>):
</label>
<select id="tunnelVariance" name="tunnelVariance" title="Level of Randomization for Tunnel Depth" class="selectbox">
<% int tunnelVariance = editBean.getTunnelVariance(curTunnel, 0);
%><option value="0"<%=(tunnelVariance == 0 ? " selected=\"selected\"" : "") %>>0 hop variance (no randomisation, consistant performance)</option>
<option value="1"<%=(tunnelVariance == 1 ? " selected=\"selected\"" : "") %>>+ 0-1 hop variance (medium additive randomisation, subtractive performance)</option>
<option value="2"<%=(tunnelVariance == 2 ? " selected=\"selected\"" : "") %>>+ 0-2 hop variance (high additive randomisation, subtractive performance)</option>
<option value="-1"<%=(tunnelVariance == -1 ? " selected=\"selected\"" : "") %>>+/- 0-1 hop variance (standard randomisation, standard performance)</option>
<option value="-2"<%=(tunnelVariance == -2 ? " selected=\"selected\"" : "") %>>+/- 0-2 hop variance (not recommended)</option>
%><option value="0"<%=(tunnelVariance == 0 ? " selected=\"selected\"" : "") %>><%=intl._("0 hop variance (no randomisation, consistant performance)")%></option>
<option value="1"<%=(tunnelVariance == 1 ? " selected=\"selected\"" : "") %>><%=intl._("+ 0-1 hop variance (medium additive randomisation, subtractive performance)")%></option>
<option value="2"<%=(tunnelVariance == 2 ? " selected=\"selected\"" : "") %>><%=intl._("+ 0-2 hop variance (high additive randomisation, subtractive performance)")%></option>
<option value="-1"<%=(tunnelVariance == -1 ? " selected=\"selected\"" : "") %>><%=intl._("+/- 0-1 hop variance (standard randomisation, standard performance)")%></option>
<option value="-2"<%=(tunnelVariance == -2 ? " selected=\"selected\"" : "") %>><%=intl._("+/- 0-2 hop variance (not recommended)")%></option>
<% if (tunnelVariance > 2 || tunnelVariance < -2) {
%> <option value="<%=tunnelVariance%>" selected="selected"><%= (tunnelVariance > 2 ? "+ " : "+/- ") %>0-<%=tunnelVariance%> hop variance</option>
%> <option value="<%=tunnelVariance%>" selected="selected"><%= (tunnelVariance > 2 ? "+ " : "+/- ") %>0-<%=tunnelVariance%> <%=intl._("hop variance")%></option>
<% }
%></select>
</div>
<div id="countField" class="rowItem">
<label for="tunnelQuantity" accesskey="C">
<span class="accessKey">C</span>ount:
<%=intl._("Count")%>(<span class="accessKey">C</span>):
</label>
<select id="tunnelQuantity" name="tunnelQuantity" title="Number of Tunnels in Group" class="selectbox">
<% int tunnelQuantity = editBean.getTunnelQuantity(curTunnel, 2);
%><option value="1"<%=(tunnelQuantity == 1 ? " selected=\"selected\"" : "") %>>1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)</option>
<option value="2"<%=(tunnelQuantity == 2 ? " selected=\"selected\"" : "") %>>2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)</option>
<option value="3"<%=(tunnelQuantity == 3 ? " selected=\"selected\"" : "") %>>3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)</option>
%><option value="1"<%=(tunnelQuantity == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)")%></option>
<option value="2"<%=(tunnelQuantity == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)")%></option>
<option value="3"<%=(tunnelQuantity == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)")%></option>
<% if (tunnelQuantity > 3) {
%> <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> tunnels</option>
%> <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> <%=intl._("tunnels")%></option>
<% }
%></select>
</div>
<div id="backupField" class="rowItem">
<label for="tunnelBackupQuantity" accesskey="b">
<span class="accessKey">B</span>ackup Count:
<%=intl._("Backup Count")%>(<span class="accessKey">B</span>):
</label>
<select id="tunnelBackupQuantity" name="tunnelBackupQuantity" title="Number of Reserve Tunnels" class="selectbox">
<% int tunnelBackupQuantity = editBean.getTunnelBackupQuantity(curTunnel, 0);
%><option value="0"<%=(tunnelBackupQuantity == 0 ? " selected=\"selected\"" : "") %>>0 backup tunnels (0 redundancy, no added resource usage)</option>
<option value="1"<%=(tunnelBackupQuantity == 1 ? " selected=\"selected\"" : "") %>>1 backup tunnel each direction (low redundancy, low resource usage)</option>
<option value="2"<%=(tunnelBackupQuantity == 2 ? " selected=\"selected\"" : "") %>>2 backup tunnels each direction (medium redundancy, medium resource usage)</option>
<option value="3"<%=(tunnelBackupQuantity == 3 ? " selected=\"selected\"" : "") %>>3 backup tunnels each direction (high redundancy, high resource usage)</option>
%><option value="0"<%=(tunnelBackupQuantity == 0 ? " selected=\"selected\"" : "") %>><%=intl._("0 backup tunnels (0 redundancy, no added resource usage)")%></option>
<option value="1"<%=(tunnelBackupQuantity == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 backup tunnel each direction (low redundancy, low resource usage)")%></option>
<option value="2"<%=(tunnelBackupQuantity == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 backup tunnels each direction (medium redundancy, medium resource usage)")%></option>
<option value="3"<%=(tunnelBackupQuantity == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 backup tunnels each direction (high redundancy, high resource usage)")%></option>
<% if (tunnelBackupQuantity > 3) {
%> <option value="<%=tunnelBackupQuantity%>" selected="selected"><%=tunnelBackupQuantity%> backup tunnels</option>
%> <option value="<%=tunnelBackupQuantity%>" selected="selected"><%=tunnelBackupQuantity%> <%=intl._("backup tunnels")%></option>
<% }
%></select>
</div>
@ -236,17 +291,17 @@
</div>
<div id="optionsField" class="rowItem">
<label>I2CP Options:</label>
<label><%=intl._("I2CP Options")%>:</label>
</div>
<div id="optionsHostField" class="rowItem">
<label for="clientHost" accesskey="o">
H<span class="accessKey">o</span>st:
<%=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" />
</div>
<div id="optionsPortField" class="rowItem">
<label for="clientPort" accesskey="r">
Po<span class="accessKey">r</span>t:
<%=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" />
</div>
@ -257,27 +312,27 @@
<div id="optionsField" class="rowItem">
<label for="encrypt" accesskey="e">
<span class="accessKey">E</span>ncrypt Leaseset:
<%=intl._("Encrypt Leaseset")%>(<span class="accessKey">E</span>):
</label>
</div>
<div id="portField" class="rowItem">
<label for="encrypt" accesskey="e">
Enable:
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="encrypt" title="Encrypt LeaseSet"<%=(editBean.getEncrypt(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="portField" class="rowItem">
<label for="encrypt" accesskey="e">
Encryption Key:
<%=intl._("Encryption Key")%>:
</label>
<textarea rows="1" style="height: 3em;" cols="44" id="portField" name="encryptKey" title="Encrypt Key" wrap="off"><%=editBean.getEncryptKey(curTunnel)%></textarea>
</div>
<div id="portField" class="rowItem">
<label for="force" accesskey="c">
Generate New Key:
<%=intl._("Generate New Key")%>:
</label>
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Generate" title="Generate New Key Now">Generate</button>
<span class="comment">(Tunnel must be stopped first)</span>
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Generate" title="Generate New Key Now"><%=intl._("Generate")%></button>
<span class="comment"><%=intl._("(Tunnel must be stopped first)")%></span>
</div>
<div class="subdivider">
@ -286,21 +341,21 @@
<div id="optionsField" class="rowItem">
<label for="access" accesskey="s">
Restricted Acce<span class="accessKey">s</span>s List: <i>Unimplemented</i>
<%=intl._("Restricted Access List")%>(<span class="accessKey">s</span>): <i><%=intl._("Unimplemented")%></i>
</label>
</div>
<div id="portField" class="rowItem">
<label for="access" accesskey="s">
Enable:
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="access" title="Enable Access List"<%=(editBean.getAccess(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="hostField" class="rowItem">
<label for="accessList" accesskey="s">
Access List:
<%=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">(Restrict to these clients only)</span>
<span class="comment"><%=intl._("(Restrict to these clients only)")%></span>
</div>
<div class="subdivider">
@ -309,24 +364,24 @@
<div id="optionsField" class="rowItem">
<label for="reduce" accesskey="d">
Re<span class="accessKey">d</span>uce tunnel quantity when idle:
<%=intl._("Reduce tunnel quantity when idle")%>(<span class="accessKey">d</span>):
</label>
</div>
<div id="portField" class="rowItem">
<label for="access" accesskey="d">
Enable:
<%=intl._("Enable")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="reduce" title="Reduce Tunnels"<%=(editBean.getReduce(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
</div>
<div id="portField" class="rowItem">
<label for="reduceCount" accesskey="d">
Reduced tunnel count:
<%=intl._("Reduced tunnel count")%>:
</label>
<input type="text" id="port" name="reduceCount" size="1" maxlength="1" title="Reduced Tunnel Count" value="<%=editBean.getReduceCount(curTunnel)%>" class="freetext" />
</div>
<div id="portField" class="rowItem">
<label for="reduceTime" accesskey="d">
Idle minutes:
<%=intl._("Idle minutes")%>:
</label>
<input type="text" id="port" name="reduceTime" size="4" maxlength="4" title="Reduced Tunnel Idle Time" value="<%=editBean.getReduceTime(curTunnel)%>" class="freetext" />
</div>
@ -337,36 +392,36 @@
<div id="tunnelOptionsField" class="rowItem">
<label for="cert" accesskey="c">
New <span class="accessKey">C</span>ertificate type:
<%=intl._("New Certificate type")%>(<span class="accessKey">C</span>):
</label>
</div>
<div id="hostField" class="rowItem">
<div id="portField" class="rowItem">
<label>None</label>
<label><%=intl._("None")%></label>
<input value="0" type="radio" id="startOnLoad" name="cert" title="No Certificate"<%=(editBean.getCert(curTunnel)==0 ? " checked=\"checked\"" : "")%> class="tickbox" />
<span class="comment"></span>
</div>
<div id="portField" class="rowItem">
<label>Hashcash (effort)</label>
<label><%=intl._("Hashcash (effort)")%></label>
<input value="1" type="radio" id="startOnLoad" name="cert" title="Hashcash Certificate"<%=(editBean.getCert(curTunnel)==1 ? " checked=\"checked\"" : "")%> class="tickbox" />
<input type="text" id="port" name="effort" size="2" maxlength="2" title="Hashcash Effort" value="<%=editBean.getEffort(curTunnel)%>" class="freetext" />
</div>
</div>
<div id="portField" class="rowItem">
<label for="force" accesskey="c">
Hashcash Calc Time:
<%=intl._("Hashcash Calc Time")%>:
</label>
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Estimate" title="Estimate Calculation Time">Estimate</button>
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Estimate" title="Estimate Calculation Time"><%=intl._("Estimate")%></button>
</div>
<div id="hostField" class="rowItem">
<div id="portField" class="rowItem">
<label>Hidden</label>
<label><%=intl._("Hidden")%></label>
<input value="2" type="radio" id="startOnLoad" name="cert" title="Hidden Certificate"<%=(editBean.getCert(curTunnel)==2 ? " checked=\"checked\"" : "")%> class="tickbox" />
<span class="comment"></span>
</div>
<div id="portField" class="rowItem">
<label for="signer" accesskey="c">
Signed (signed by):
<%=intl._("Signed (signed by)")%>:
</label>
<input value="3" type="radio" id="startOnLoad" name="cert" title="Signed Certificate"<%=(editBean.getCert(curTunnel)==3 ? " checked=\"checked\"" : "")%> class="tickbox" />
<input type="text" id="port" name="signer" size="50" title="Cert Signer" value="<%=editBean.getSigner(curTunnel)%>" class="freetext" />
@ -375,10 +430,10 @@
</div>
<div id="portField" class="rowItem">
<label for="force" accesskey="c">
Modify Certificate:
<%=intl._("Modify Certificate")%>:
</label>
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Modify" title="Force New Cert Now">Modify</button>
<span class="comment">(Tunnel must be stopped first)</span>
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Modify" title="Force New Cert Now"><%=intl._("Modify")%></button>
<span class="comment"><%=intl._("(Tunnel must be stopped first)")%></span>
</div>
<div class="subdivider">
@ -387,7 +442,7 @@
<div id="customOptionsField" class="rowItem">
<label for="customOptions" accesskey="u">
C<span class="accessKey">u</span>stom options:
<%=intl._("Custom options")%>(<span class="accessKey">u</span>):
</label>
<input type="text" id="customOptions" name="customOptions" size="60" title="Custom Options" value="<%=editBean.getCustomOptions(curTunnel)%>" class="freetext" />
</div>
@ -399,12 +454,12 @@
<div class="header"></div>
<div class="footer">
<div class="toolbox">
<span class="comment">NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted.</span>
<span class="comment"><%=intl._("NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted.")%></span>
<div class="separator"><hr /></div>
<input type="hidden" value="true" name="removeConfirm" />
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Save changes" title="Save Changes"><span class="accessKey">S</span>ave</button>
<button id="controlDelete" <%=(editBean.allowJS() ? "onclick=\"if (!confirm('Are you sure you want to delete?')) { return false; }\" " : "")%>accesskey="D" class="control" type="submit" name="action" value="Delete this proxy" title="Delete this Proxy"><span class="accessKey">D</span>elete</button>
<button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel">Cancel</button>
<button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Save changes" title="Save Changes"><%=intl._("Save")%>(<span class="accessKey">S</span>)</button>
<button id="controlDelete" <%=(editBean.allowJS() ? "onclick=\"if (!confirm('Are you sure you want to delete?')) { return false; }\" " : "")%>accesskey="D" class="control" type="submit" name="action" value="Delete this proxy" title="Delete this Proxy"><%=intl._("Delete")%>(<span class="accessKey">D</span>)</button>
<button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel"><%=intl._("Cancel")%></button>
</div>
</div>
</div>

View File

@ -8,9 +8,10 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<jsp:useBean class="net.i2p.i2ptunnel.web.IndexBean" id="indexBean" scope="request" />
<jsp:setProperty name="indexBean" property="*" />
<jsp:useBean class="net.i2p.i2ptunnel.web.Messages" id="intl" scope="request" />
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>I2P Tunnel Manager - List</title>
<title><%=intl._("I2P Tunnel Manager - List")%></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
@ -28,7 +29,7 @@
<div id="statusMessagePanel" class="panel">
<div class="header">
<h4>Status Messages</h4>
<h4><%=intl._("Status Messages")%></h4>
</div>
<div class="separator">
@ -43,7 +44,7 @@
<div class="footer">
<div class="toolbox">
<a class="control" href="index.jsp">Refresh</a>
<a class="control" href="index.jsp"><%=intl._("Refresh")%></a>
</div>
</div>
</div>
@ -52,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">Stop All</a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=Start%20all">Start All</a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=Restart%20all">Restart All</a> <a class="control" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=Reload%20configuration">Reload Config</a>
<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>
</div>
</div>
</div>
@ -62,23 +63,23 @@
<div id="localServerTunnelList" class="panel">
<div class="header">
<h4>I2P Server Tunnels</h4>
<h4><%=intl._("I2P Server Tunnels")%></h4>
</div>
<div class="separator"> </div>
<div class="nameHeaderField rowItem">
<label>Name:</label>
<label><%=intl._("Name")%>:</label>
</div>
<div class="previewHeaderField rowItem">
<label>Points at:</label>
<label><%=intl._("Points at")%>:</label>
</div>
<div class="targetHeaderField rowItem">
<label>Preview:</label>
<label><%=intl._("Preview")%>:</label>
</div>
<div class="statusHeaderField rowItem">
<label>Status:</label>
<label><%=intl._("Status")%>:</label>
<hr /> </div>
<%
@ -87,11 +88,11 @@
%>
<div class="nameField rowItem">
<label>Name:</label>
<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>
</div>
<div class="previewField rowItem">
<label>Points at:</label>
<label><%=intl._("Points at")%>:</label>
<span class="text">
<%
if ("httpserver".equals(indexBean.getInternalType(curServer))) {
@ -106,42 +107,42 @@
</div>
<div class="targetField rowItem">
<%
if ("httpserver".equals(indexBean.getInternalType(curServer)) && indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
%><label>Preview:</label>
<a class="control" title="Test HTTP server through I2P" href="http://<%=indexBean.getDestHashBase32(curServer)%>.b32.i2p">Preview</a>
if (("httpserver".equals(indexBean.getInternalType(curServer)) || ("httpbidirserver".equals(indexBean.getInternalType(curServer)))) && indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
%><label><%=intl._("Preview")%>:</label>
<a class="control" title="Test HTTP server through I2P" href="http://<%=indexBean.getDestHashBase32(curServer)%>.b32.i2p"><%=intl._("Preview")%></a>
<%
} else if (indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
%><span class="text">Base32 Address:<br /><%=indexBean.getDestHashBase32(curServer)%>.b32.i2p</span>
%><span class="text"><%=intl._("Base32 Address")%>:<br /><%=indexBean.getDestHashBase32(curServer)%>.b32.i2p</span>
<%
} else {
%><span class="comment">No Preview</span>
%><span class="comment"><%=intl._("No Preview")%></span>
<%
}
%></div>
<div class="statusField rowItem">
<label>Status:</label>
<label><%=intl._("Status")%>:</label>
<%
switch (indexBean.getTunnelStatus(curServer)) {
case IndexBean.STARTING:
%><div class="statusStarting text">Starting...</div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curServer%>">Stop</a>
%><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>
<%
break;
case IndexBean.RUNNING:
%><div class="statusRunning text">Running</div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curServer%>">Stop</a>
%><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>
<%
break;
case IndexBean.NOT_RUNNING:
%><div class="statusNotRunning text">Stopped</div>
<a class="control" title="Start this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=start&amp;tunnel=<%=curServer%>">Start</a>
%><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>
<%
break;
}
%></div>
<div class="descriptionField rowItem">
<label>Description:</label>
<label><%=intl._("Description")%>:</label>
<div class="text"><%=indexBean.getTunnelDescription(curServer)%></div>
</div>
@ -159,14 +160,15 @@
<form id="addNewServerTunnelForm" action="edit.jsp">
<div class="toolbox">
<label>New server tunnel:</label>
<label><%=intl._("New server tunnel")%>:</label>
<select name="type">
<option value="server">Standard</option>
<option value="server"><%=intl._("Standard")%></option>
<option value="httpserver">HTTP</option>
<option value="httpbidirserver">HTTP bidir</option>
<option value="ircserver">IRC</option>
<option value="streamrserver">Streamr</option>
</select>
<input class="control" type="submit" value="Create" />
<input class="control" type="submit" value="<%=intl._("Create")%>" />
</div>
</form>
</div>
@ -176,26 +178,26 @@
<div id="localClientTunnelList" class="panel">
<div class="header">
<h4>I2P Client Tunnels</h4>
<h4><%=intl._("I2P Client Tunnels")%></h4>
</div>
<div class="separator"> </div>
<div class="nameHeaderField rowItem">
<label>Name:</label>
<label><%=intl._("Name")%>:</label>
</div>
<div class="portHeaderField rowItem">
<label>Port:</label>
<label><%=intl._("Port")%>:</label>
</div>
<div class="typeHeaderField rowItem">
<label>Type:</label>
<label><%=intl._("Type")%>:</label>
</div>
<div class="interfaceHeaderField rowItem">
<label>Interface:</label>
<label><%=intl._("Interface")%>:</label>
</div>
<div class="statusHeaderField rowItem">
<label>Status:</label>
<label><%=intl._("Status")%>:</label>
</div>
<div class="separator">
@ -206,43 +208,43 @@
if (!indexBean.isClient(curClient)) continue;
%>
<div class="nameField rowItem">
<label>Name:</label>
<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>
</div>
<div class="portField rowItem">
<label>Port:</label>
<label><%=intl._("Port")%>:</label>
<span class="text"><%=indexBean.getClientPort(curClient)%></span>
</div>
<div class="typeField rowItem">
<label>Type:</label>
<label><%=intl._("Type")%>:</label>
<span class="text"><%=indexBean.getTunnelType(curClient)%></span>
</div>
<div class="interfaceField rowItem">
<label>Interface:</label>
<label><%=intl._("Interface")%>:</label>
<span class="text"><%=indexBean.getClientInterface(curClient)%></span>
</div>
<div class="statusField rowItem">
<label>Status:</label>
<label><%=intl._("Status")%>:</label>
<%
switch (indexBean.getTunnelStatus(curClient)) {
case IndexBean.STARTING:
%><div class="statusStarting text">Starting...</div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>">Stop</a>
%><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>
<%
break;
case IndexBean.STANDBY:
%><div class="statusStarting text">Standby</div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>">Stop</a>
%><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>
<%
break;
case IndexBean.RUNNING:
%><div class="statusRunning text">Running</div>
<a class="control" title="Stop this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=stop&amp;tunnel=<%=curClient%>">Stop</a>
%><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>
<%
break;
case IndexBean.NOT_RUNNING:
%><div class="statusNotRunning text">Stopped</div>
<a class="control" title="Start this Tunnel" href="index.jsp?nonce=<%=indexBean.getNextNonce()%>&amp;action=start&amp;tunnel=<%=curClient%>">Start</a>
%><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>
<%
break;
}
@ -252,9 +254,9 @@
<div class="destinationField rowItem">
<label>
<% if ("httpclient".equals(indexBean.getInternalType(curClient)) || "connectclient".equals(indexBean.getInternalType(curClient))) { %>
Outproxy:
<%=intl._("Outproxy")%>:
<% } else { %>
Destination:
<%=intl._("Destination")%>:
<% } %>
</label>
<input class="freetext" size="40" readonly="readonly" value="<%=indexBean.getClientDestination(curClient)%>" />
@ -262,7 +264,7 @@
<% } %>
<div class="descriptionField rowItem">
<label>Description:</label>
<label><%=intl._("Description")%>:</label>
<div class="text"><%=indexBean.getTunnelDescription(curClient)%></div>
</div>
@ -280,16 +282,16 @@
<form id="addNewClientTunnelForm" action="edit.jsp">
<div class="toolbox">
<label>New client tunnel:</label>
<label><%=intl._("New client tunnel")%>:</label>
<select name="type">
<option value="client">Standard</option>
<option value="client"><%=intl._("Standard")%></option>
<option value="httpclient">HTTP</option>
<option value="ircclient">IRC</option>
<option value="sockstunnel">SOCKS 4/4a/5</option>
<option value="connectclient">CONNECT</option>
<option value="streamrclient">Streamr</option>
</select>
<input class="control" type="submit" value="Create" />
<input class="control" type="submit" value="<%=intl._("Create")%>" />
</div>
</form>
</div>

View File

@ -0,0 +1,30 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2ptunnel package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-12-10 00:50+0000\n"
"PO-Revision-Date: 2009-10-19 12:50+0000\n"
"Last-Translator: foo <foo@bar>\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"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:73
msgid "I2P Tunnel Manager - Edit Client Tunnel"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:73
msgid "I2P Tunnel Manager - Edit Server Tunnel"
msgstr ""
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:71
msgid "I2P Tunnel Manager - List"
msgstr ""

View File

@ -0,0 +1,675 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2ptunnel package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-01-14 06:24+0000\n"
"PO-Revision-Date: 2010-01-18 18:40+0000\n"
"Last-Translator: 4get <forget@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: Russian\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:436
#, java-format
msgid "To visit the destination in your host database, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper link by temporarily giving it a random alias, click <a href=\"{1}\">here</a>."
msgstr "Для перехода по ссылке из локальной адресной книги, нажмите <a href=\"{0}\">здесь</a>. Для перехода по новой addresshelper-ссылке с временным присвоением ей случайного имени, нажмите <a href=\"{1}\">здесь</a>."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:802
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:362
msgid "New Tunnel"
msgstr "Новый туннель"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:382
msgid "Standard client"
msgstr "Обычный клиент"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:383
msgid "HTTP client"
msgstr "HTTP-клиент"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:384
msgid "IRC client"
msgstr "IRC-клиент"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:385
msgid "Standard server"
msgstr "Обычный сервер"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:386
msgid "HTTP server"
msgstr "HTTP-сервер"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:387
msgid "SOCKS 4/4a/5 proxy"
msgstr "SOCKS 4/4a/5 прокси"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:388
msgid "CONNECT/SSL/HTTPS proxy"
msgstr "CONNECT/SSL/HTTPS прокси"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:389
msgid "IRC server"
msgstr "IRC-сервер"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:390
msgid "Streamr client"
msgstr "Streamr-клиент"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:391
msgid "Streamr server"
msgstr "Streamr-сервер"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:392
msgid "HTTP bidir"
msgstr "HTTP bidir (экспериментальный двунаправленный режим, инструкцию спрашивайте у sponge)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:73
msgid "I2P Tunnel Manager - Edit Client Tunnel"
msgstr "Менеджер Туннелей I2P — Редактирование Клиентского Туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:93
msgid "Edit proxy settings"
msgstr "Редактирование настроек клиентского туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:101
msgid "New proxy settings"
msgstr "Настройки нового клиентского туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:112
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:112
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:107
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:121
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:242
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:257
msgid "Name"
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
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:357
msgid "Description"
msgstr "Описание"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:126
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:136
msgid "Target"
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
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
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
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
msgid "Outproxies"
msgstr "Список outproxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:202
msgid "Tunnel Destination"
msgstr "Адрес назначения туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:214
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: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
msgid "Shared Client"
msgstr "Коллективный клиент"
#: ../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 "(Использовать туннели коллективно/совместно с другими прокси-клиентами? Изменение настройки потребует перезапуска туннеля)"
#: ../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 "Автозапуск"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:251
#: ../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
msgid "Advanced networking options"
msgstr "Расширенные сетевые настройки"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:255
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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: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
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/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
msgid "Reduce tunnel quantity when idle"
msgstr "Снижать количество туннелей при простое"
#: ../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:435
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:447
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
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
msgid "Idle minutes"
msgstr "Минут простоя"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:420
msgid "Close tunnels when idle"
msgstr "Закрыть туннели при простое"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:426
msgid "New Keys on Reopen"
msgstr "Генерировать новый ключ при переоткрытии"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:434
msgid "Disable"
msgstr "Выключить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:440
msgid "Delay tunnel open until required"
msgstr "Отложить запуск до первого запроса"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:450
msgid "Persistent private key"
msgstr "Постоянный секретный ключ"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:456
msgid "File"
msgstr "Файл"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:460
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:252
msgid "Local destination"
msgstr "Локальный адрес назначения"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:464
msgid "(if known)"
msgstr "(если известен)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:468
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:491
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
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:478
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:501
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/editServer_jsp.java:73
msgid "I2P Tunnel Manager - Edit Server Tunnel"
msgstr "Менеджер Туннелей I2P — Редактирование Серверного Туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:93
msgid "Edit server settings"
msgstr "Редактирование настроек серверного туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:101
msgid "New server settings"
msgstr "Настройки нового серверного туннеля"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:214
msgid "Website name"
msgstr "Имя веб-сайта"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:218
msgid "(leave blank for outproxies)"
msgstr "(не заполнять для outproxy)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:223
msgid "Private key file"
msgstr "Файл секретного ключа"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:262
msgid "Add to local addressbook"
msgstr "Добавить в локальную адресную книгу"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:415
msgid "Encrypt Leaseset"
msgstr "Шифровать LeaseSet"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:421
msgid "Encryption Key"
msgstr "Ключ шифрования"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:425
msgid "Generate New Key"
msgstr "Сгенерировать новый ключ"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:427
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
msgid "(Tunnel must be stopped first)"
msgstr "(Туннель перед этим следует остановить)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:431
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 "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:459
msgid "New Certificate type"
msgstr "Создать новый сертификат. Тип"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:461
msgid "None"
msgstr "Без"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:465
msgid "Hashcash (effort)"
msgstr "Hashcash (экспериментальный)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:471
msgid "Hashcash Calc Time"
msgstr "Время генерации hashcash-сертификата"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:473
msgid "Estimate"
msgstr "Прогноз"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:475
msgid "Hidden"
msgstr "Скрытый"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:479
msgid "Signed (signed by)"
msgstr "Подписанный (указать кем подписан)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:485
msgid "Modify Certificate"
msgstr "Изменить сертификат"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:487
msgid "Modify"
msgstr "Изменить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:71
msgid "I2P Tunnel Manager - List"
msgstr "Менеджер Туннелей I2P — Список"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:83
msgid "Status Messages"
msgstr "Сообщения о состоянии"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:87
msgid "Refresh"
msgstr "Обновить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:91
msgid "Stop All"
msgstr "Остановить все"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:95
msgid "Start All"
msgstr "Запустить все"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:99
msgid "Restart All"
msgstr "Перезапустить все"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:103
msgid "Reload Config"
msgstr "Перезагрузить настройки"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:105
msgid "I2P Server Tunnels"
msgstr "Серверные I2P туннели"
#: ../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 "Указывает на"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:111
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:153
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:157
msgid "Preview"
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
msgid "Status"
msgstr "Состояние"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:163
msgid "Base32 Address"
msgstr "Base32-адрес"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:171
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
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
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
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
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
msgid "Start"
msgstr "Запустить"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:234
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:367
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:369
msgid "Create"
msgstr "Создать"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:240
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
msgid "Interface"
msgstr "Сетевой интерфейс"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:299
msgid "Standby"
msgstr "Режим ожидания"
# This term intentionally left in English
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:345
msgid "Outproxy"
msgstr "Outproxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:349
msgid "Destination"
msgstr "Адрес назначения"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:365
msgid "New client tunnel"
msgstr "Новый клиентский туннель"

View File

@ -0,0 +1,674 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the i2ptunnel package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P i2ptunnel\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-01-29 07:17+0000\n"
"PO-Revision-Date: 2010-01-29 15:31+0800\n"
"Last-Translator: walking <zhazhenzhong@gmail.com>\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: Chinese\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:436
#, java-format
msgid "To visit the destination in your host database, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper link by temporarily giving it a random alias, click <a href=\"{1}\">here</a>."
msgstr "要访问您本地【地址簿】中规定的主机(相当与IP),请点击<a href=\"{0}\">这里</a>。要访问【地址助手】返回的主机请点<a href=\"{1}\">这里</a>(主机的域名会被临时强制替换)。"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:802
msgid "Click a link below to look for an address helper by using a \"jump\" service:"
msgstr "请点击下面的链接通过【跳转(Jump)】服务提供的【地址助手】链接跳转至域名对应的主机:"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:362
msgid "New Tunnel"
msgstr "新建隧道"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:382
msgid "Standard client"
msgstr "标准客户端"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:383
msgid "HTTP client"
msgstr "HTTP 客户端"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:384
msgid "IRC client"
msgstr "IRC 客户端"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:385
msgid "Standard server"
msgstr "标准服务器"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:386
msgid "HTTP server"
msgstr "HTTP 服务器"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:387
msgid "SOCKS 4/4a/5 proxy"
msgstr "SOCKS4/4A/5 代理"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:388
msgid "CONNECT/SSL/HTTPS proxy"
msgstr "CONNECT/SSL/HTTPS 代理"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:389
msgid "IRC server"
msgstr "IRC 服务器"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:390
msgid "Streamr client"
msgstr "Streamr 客户端"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:391
msgid "Streamr server"
msgstr "Streamr 服务器"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:392
msgid "HTTP bidir"
msgstr "双向http"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:73
msgid "I2P Tunnel Manager - Edit Client Tunnel"
msgstr "I2P 隧道管理器 - 编辑客户端隧道"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:93
msgid "Edit proxy settings"
msgstr "编辑代理设置"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:101
msgid "New proxy settings"
msgstr "新建代理设置"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:112
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:112
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:107
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:121
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:242
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:257
msgid "Name"
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
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:357
msgid "Description"
msgstr "描述"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:126
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:136
msgid "Target"
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
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
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
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
msgid "Outproxies"
msgstr "出口代理"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:202
msgid "Tunnel Destination"
msgstr "隧道目标"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:214
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:227
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:244
msgid "interactive connection"
msgstr "速度连接"
#: ../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 "效率连接(下载/WEB/BT)"
#: ../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
msgid "Shared Client"
msgstr "共享客户端"
#: ../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 "(与其他客户端例如IRC/HTTP共享隧道修改需要重新启动)"
#: ../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 "自动启动"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:251
#: ../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
msgid "Advanced networking options"
msgstr "高级网络设置"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:255
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
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
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
msgid "0 hop tunnel (low anonymity, low latency)"
msgstr "直连(匿名性无,延迟低)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:270
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281
msgid "1 hop tunnel (medium anonymity, medium latency)"
msgstr "隧道跳点x1(匿名性中,延迟中)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:274
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:285
msgid "2 hop tunnel (high anonymity, high latency)"
msgstr "隧道跳点x2(匿名性高,延迟高)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:278
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:289
msgid "3 hop tunnel (very high anonymity, poor performance)"
msgstr "隧道跳点x3(匿名性优,影响性能)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:287
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:298
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
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
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
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
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
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
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
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
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
msgid "1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)"
msgstr "出/入站隧道x1(带宽低,低可靠性)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:343
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:354
msgid "2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)"
msgstr "出/入站隧道x2(带宽标准,标准稳定性)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:347
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:358
msgid "3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)"
msgstr "出/入站隧道x3(带宽高,高稳定性)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:356
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:367
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
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
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
msgid "1 backup tunnel each direction (low redundancy, low resource usage)"
msgstr "备用隧道对x1 (低冗余,低资源占用)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:376
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:387
msgid "2 backup tunnels each direction (medium redundancy, medium resource usage)"
msgstr "备用隧道对x2 (中冗余,中资源占用)"
#: ../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 "备用隧道对x3 (高冗余,高资源占用)"
#: ../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 "备用隧道"
#: ../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: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
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/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
msgid "Reduce tunnel quantity when idle"
msgstr "空闲时缩减隧道数量"
#: ../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:435
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:447
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
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
msgid "Idle minutes"
msgstr "空闲时间(分钟)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:420
msgid "Close tunnels when idle"
msgstr "空闲时关闭隧道"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:426
msgid "New Keys on Reopen"
msgstr "重新打开隧道时使用新密钥"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:434
msgid "Disable"
msgstr "禁用"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:440
msgid "Delay tunnel open until required"
msgstr "仅在请求时打开"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:450
msgid "Persistent private key"
msgstr "永久私有密钥"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:456
msgid "File"
msgstr "文件"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:460
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:252
msgid "Local destination"
msgstr "本地目标"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:464
msgid "(if known)"
msgstr "(如果已知)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:468
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:491
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
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:478
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:501
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/editServer_jsp.java:73
msgid "I2P Tunnel Manager - Edit Server Tunnel"
msgstr "I2P隧道管理器 - 编辑服务器隧道"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:93
msgid "Edit server settings"
msgstr "服务器隧道设置"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:101
msgid "New server settings"
msgstr "新建服务器设置"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:214
msgid "Website name"
msgstr "网站名称"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:218
msgid "(leave blank for outproxies)"
msgstr "(出口代理这里请置空)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:223
msgid "Private key file"
msgstr "私钥文件"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:262
msgid "Add to local addressbook"
msgstr "添加至本地地址簿"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:415
msgid "Encrypt Leaseset"
msgstr "加密赁集"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:421
msgid "Encryption Key"
msgstr "加密密钥"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:425
msgid "Generate New Key"
msgstr "生成新密钥"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:427
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
msgid "(Tunnel must be stopped first)"
msgstr "(必须先停止隧道)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:431
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 "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:459
msgid "New Certificate type"
msgstr "新建证书类型"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:461
msgid "None"
msgstr "无"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:465
msgid "Hashcash (effort)"
msgstr "Hashcash (强度)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:471
msgid "Hashcash Calc Time"
msgstr "Hashcash 计算时间"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:473
msgid "Estimate"
msgstr "估算"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:475
msgid "Hidden"
msgstr "隐藏"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:479
msgid "Signed (signed by)"
msgstr "签名(签名者)"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:485
msgid "Modify Certificate"
msgstr "修改证书"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:487
msgid "Modify"
msgstr "修改"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:71
msgid "I2P Tunnel Manager - List"
msgstr "I2P隧道管理器 - 列表"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:83
msgid "Status Messages"
msgstr "状态信息"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:87
msgid "Refresh"
msgstr "刷新"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:91
msgid "Stop All"
msgstr "全部停止"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:95
msgid "Start All"
msgstr "全部启动"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:99
msgid "Restart All"
msgstr "全部重启"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:103
msgid "Reload Config"
msgstr "重新载入设置"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:105
msgid "I2P Server Tunnels"
msgstr "I2P服务端隧道"
#: ../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 "指向"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:111
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:153
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:157
msgid "Preview"
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
msgid "Status"
msgstr "状态"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:163
msgid "Base32 Address"
msgstr "Base32地址"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:171
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
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
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
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
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
msgid "Start"
msgstr "启动"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:234
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:367
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:369
msgid "Create"
msgstr "创建"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:240
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
msgid "Interface"
msgstr "网络接口"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:299
msgid "Standby"
msgstr "等待"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:345
msgid "Outproxy"
msgstr "出口代理"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:349
msgid "Destination"
msgstr "目标"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:365
msgid "New client tunnel"
msgstr "新建客户隧道"

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="jetty">
<property name="jetty.sha1" value="021164f84da7304bd1ff07c268b45aa3e0b13322" />
<property name="jetty.md5" value="a61adc832be6baf2678935506743cfc3" />
<property name="jetty.url" value="http://dist.codehaus.org/jetty/jetty-5.1.x/jetty-5.1.12.zip" />
<property name="jetty.filename" value="jetty-5.1.12.zip" />
<property name="jetty.base" value="jetty-5.1.15" />
<property name="jetty.sha1" value="3a7a3de50f86f0cdb23c33aec632ea7f44132c5e" />
<property name="jetty.filename" value="${jetty.base}.tgz" />
<property name="jetty.url" value="http://dist.codehaus.org/jetty/jetty-5.1.x/${jetty.filename}" />
<property name="verified.filename" value="verified.txt" />
<property name="javac.compilerargs" value="" />
@ -32,7 +32,6 @@
<echo message="Even if you deploy the Jetty archive manually, the build script will" />
<echo message="still attempt to verify its checksums, which must be:" />
<echo message="SHA1 ${jetty.sha1}" />
<echo message="MD5 ${jetty.md5}" />
<echo message="" />
<input message="Download Jetty archive automatically?" validargs="y,n" addproperty="jetty.download" />
<fail message="Aborting as requested. Please deploy the Jetty archive manually." >
@ -43,16 +42,18 @@
<get src="${jetty.url}" verbose="true" dest="${jetty.filename}" />
</target>
<uptodate property="verified.already" srcfile="${jetty.filename}" targetfile="${verified.filename}" />
<condition property="verified.already" >
<and>
<available file="${jetty.filename}" />
<uptodate property="foo.bar.baz" srcfile="${jetty.filename}" targetfile="${verified.filename}" />
</and>
</condition>
<target name="verifyJettylib" unless="verified.already" >
<condition property="jetty.zip.verified" >
<and>
<checksum file="${jetty.filename}" algorithm="SHA" property="${jetty.sha1}" />
<checksum file="${jetty.filename}" algorithm="MD5" property="${jetty.md5}" />
</and>
</condition>
<fail message="Jetty archive does not match its checksums!" >
<fail message="Jetty archive does not match its checksum!" >
<condition>
<not>
<istrue value="${jetty.zip.verified}" />
@ -63,15 +64,16 @@
</target>
<target name="extractJettylib" unless="jetty.zip.extracted" >
<unzip src="${jetty.filename}" dest="." />
<gunzip src="${jetty.filename}" dest="jetty.tar" />
<untar src="jetty.tar" dest="." />
<mkdir dir="jettylib" />
<copy todir="jettylib">
<fileset dir="jetty-5.1.12/lib">
<fileset dir="${jetty.base}/lib">
<include name="*.jar" />
</fileset>
</copy>
<copy todir="jettylib">
<fileset dir="jetty-5.1.12/ext">
<fileset dir="${jetty.base}/ext">
<include name="ant.jar" />
<include name="commons-el.jar" />
<include name="commons-logging.jar" />
@ -81,7 +83,8 @@
<include name="org.mortbay.jetty.jar" />
</fileset>
</copy>
<delete dir="jetty-5.1.12" />
<delete file="jetty.tar" />
<delete dir="${jetty.base}" />
</target>
<target name="build" depends="jar" />
@ -107,10 +110,10 @@
</target>
<target name="cleandep" depends="clean" />
<target name="distclean" depends="clean">
<delete dir="./jettylib" />
<echo message="Not actually deleting the jetty libs (since they're so large)" />
</target>
<target name="reallyclean" depends="distclean">
<delete dir="./jettylib" />
</target>
<target name="totallyclean" depends="clean">
<delete dir="./jettylib" />
@ -128,9 +131,9 @@
<mkdir dir="./build/javadoc" />
<unzip src="${jetty.filename}" dest="./build/javadoc" >
<patternset>
<include name="jetty-5.1.12/javadoc/" />
<include name="${jetty.base}/javadoc/" />
</patternset>
<mapper type="glob" from="jetty-5.1.12/javadoc/*" to="javadoc/*" />
<mapper type="glob" from="${jetty.base}/javadoc/*" to="javadoc/*" />
</unzip>
</target>

View File

@ -0,0 +1,617 @@
// ========================================================================
// $Id: Server.java,v 1.40 2005/10/21 13:52:11 gregwilkins Exp $
// Copyright 2002-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.jetty;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.mortbay.log.LogFactory;
import org.mortbay.http.HttpContext;
import org.mortbay.http.HttpServer;
import org.mortbay.jetty.servlet.ServletHttpContext;
import org.mortbay.jetty.servlet.WebApplicationContext;
import org.mortbay.util.LogSupport;
import org.mortbay.util.Resource;
import org.mortbay.xml.XmlConfiguration;
/* ------------------------------------------------------------ */
/** The Jetty HttpServer.
*
* This specialization of org.mortbay.http.HttpServer adds knowledge
* about servlets and their specialized contexts. It also included
* support for initialization from xml configuration files
* that follow the XmlConfiguration dtd.
*
* HttpContexts created by Server are of the type
* org.mortbay.jetty.servlet.ServletHttpContext unless otherwise
* specified.
*
* This class also provides a main() method which starts a server for
* each config file passed on the command line. If the system
* property JETTY_NO_SHUTDOWN_HOOK is not set to true, then a shutdown
* hook is thread is registered to stop these servers.
*
* @see org.mortbay.xml.XmlConfiguration
* @see org.mortbay.jetty.servlet.ServletHttpContext
* @version $Revision: 1.40 $
* @author Greg Wilkins (gregw)
*/
public class Server extends HttpServer
{
static Log log = LogFactory.getLog(Server.class);
private String[] _webAppConfigurationClassNames =
new String[]{"org.mortbay.jetty.servlet.XMLConfiguration", "org.mortbay.jetty.servlet.JettyWebConfiguration"};
private String _configuration;
private String _rootWebApp;
private static ShutdownHookThread hookThread = new ShutdownHookThread();
/* ------------------------------------------------------------ */
/** Constructor.
*/
public Server()
{
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param configuration The filename or URL of the XML
* configuration file.
*/
public Server(String configuration)
throws IOException
{
this(Resource.newResource(configuration).getURL());
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param configuration The filename or URL of the XML
* configuration file.
*/
public Server(Resource configuration)
throws IOException
{
this(configuration.getURL());
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param configuration The filename or URL of the XML
* configuration file.
*/
public Server(URL configuration)
throws IOException
{
_configuration=configuration.toString();
Server.hookThread.add(this);
try
{
XmlConfiguration config=new XmlConfiguration(configuration);
config.configure(this);
}
catch(IOException e)
{
throw e;
}
catch(InvocationTargetException e)
{
log.warn(LogSupport.EXCEPTION,e.getTargetException());
throw new IOException("Jetty configuration problem: "+e.getTargetException());
}
catch(Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
throw new IOException("Jetty configuration problem: "+e);
}
}
/* ------------------------------------------------------------ */
public boolean getStopAtShutdown()
{
return hookThread.contains(this);
}
/* ------------------------------------------------------------ */
public void setStopAtShutdown(boolean stop)
{
if (stop)
hookThread.add(this);
else
hookThread.remove(this);
}
/* ------------------------------------------------------------ */
/** Get the root webapp name.
* @return The name of the root webapp (eg. "root" for root.war).
*/
public String getRootWebApp()
{
return _rootWebApp;
}
/* ------------------------------------------------------------ */
/** Set the root webapp name.
* @param rootWebApp The name of the root webapp (eg. "root" for root.war).
*/
public void setRootWebApp(String rootWebApp)
{
_rootWebApp = rootWebApp;
}
/* ------------------------------------------------------------ */
/** Configure the server from an XML file.
* @param configuration The filename or URL of the XML
* configuration file.
*/
public void configure(String configuration)
throws IOException
{
URL url=Resource.newResource(configuration).getURL();
if (_configuration!=null && _configuration.equals(url.toString()))
return;
if (_configuration!=null)
throw new IllegalStateException("Already configured with "+_configuration);
try
{
XmlConfiguration config=new XmlConfiguration(url);
_configuration=url.toString();
config.configure(this);
}
catch(IOException e)
{
throw e;
}
catch(Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
throw new IOException("Jetty configuration problem: "+e);
}
}
/* ------------------------------------------------------------ */
public String getConfiguration()
{
return _configuration;
}
/* ------------------------------------------------------------ */
/** Create a new ServletHttpContext.
* Ths method is called by HttpServer to creat new contexts. Thus
* calls to addContext or getContext that result in a new Context
* being created will return an
* org.mortbay.jetty.servlet.ServletHttpContext instance.
* @return ServletHttpContext
*/
protected HttpContext newHttpContext()
{
return new ServletHttpContext();
}
/* ------------------------------------------------------------ */
/** Create a new WebApplicationContext.
* Ths method is called by Server to creat new contexts for web
* applications. Thus calls to addWebApplication that result in
* a new Context being created will return an correct class instance.
* Derived class can override this method to create instance of its
* own class derived from WebApplicationContext in case it needs more
* functionality.
* @param webApp The Web application directory or WAR file.
* @return WebApplicationContext
*/
protected WebApplicationContext newWebApplicationContext(
String webApp
)
{
return new WebApplicationContext(webApp);
}
/* ------------------------------------------------------------ */
/** Add Web Application.
* @param contextPathSpec The context path spec. Which must be of
* the form / or /path/*
* @param webApp The Web application directory or WAR file.
* @return The WebApplicationContext
* @exception IOException
*/
public WebApplicationContext addWebApplication(String contextPathSpec,
String webApp)
throws IOException
{
return addWebApplication(null,contextPathSpec,webApp);
}
/* ------------------------------------------------------------ */
/** Add Web Application.
* @param virtualHost Virtual host name or null
* @param contextPathSpec The context path spec. Which must be of
* the form / or /path/*
* @param webApp The Web application directory or WAR file.
* @return The WebApplicationContext
* @exception IOException
*/
public WebApplicationContext addWebApplication(String virtualHost,
String contextPathSpec,
String webApp)
throws IOException
{
WebApplicationContext appContext =
newWebApplicationContext(webApp);
appContext.setContextPath(contextPathSpec);
addContext(virtualHost,appContext);
if(log.isDebugEnabled())log.debug("Web Application "+appContext+" added");
return appContext;
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If a
* webapp is called "root" it is added at "/".
* @param webapps Directory file name or URL to look for auto webapplication.
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String webapps)
throws IOException
{
return addWebApplications(null,webapps,null,false);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto webapplication.
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps)
throws IOException
{
return addWebApplications(host,webapps,null,false);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto
* webapplication.
* @param extract If true, extract war files
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps,
boolean extract)
throws IOException
{
return addWebApplications(host,webapps,null,extract);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto
* webapplication.
* @param defaults The defaults xml filename or URL which is
* loaded before any in the web app. Must respect the web.dtd.
* If null the default defaults file is used. If the empty string, then
* no defaults file is used.
* @param extract If true, extract war files
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps,
String defaults,
boolean extract)
throws IOException
{
return addWebApplications(host,webapps,defaults,extract,true,null);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto
* webapplication.
* @param defaults The defaults xml filename or URL which is
* loaded before any in the web app. Must respect the web.dtd.
* If null the default defaults file is used. If the empty string, then
* no defaults file is used.
* @param extract If true, extract war files
* @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps,
String defaults,
boolean extract,
boolean java2CompliantClassLoader)
throws IOException
{
return addWebApplications(host,webapps,defaults,extract,java2CompliantClassLoader,null);
}
/* ------------------------------------------------------------ */
/** Add Web Applications.
* Add auto webapplications to the server. The name of the
* webapp directory or war is used as the context name. If the
* webapp matches the rootWebApp it is added as the "/" context.
* @param host Virtual host name or null
* @param webapps Directory file name or URL to look for auto
* webapplication.
* @param defaults The defaults xml filename or URL which is
* loaded before any in the web app. Must respect the web.dtd.
* If null the default defaults file is used. If the empty string, then
* no defaults file is used.
* @param extract If true, extract war files
* @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications
* @param Attributes[] A set of attributes to pass to setAttribute, format is first item is the key, second item is the value.
* @exception IOException
*/
public WebApplicationContext[] addWebApplications(String host,
String webapps,
String defaults,
boolean extract,
boolean java2CompliantClassLoader,
String Attributes[])
throws IOException
{
ArrayList wacs = new ArrayList();
Resource r=Resource.newResource(webapps);
if (!r.exists())
throw new IllegalArgumentException("No such webapps resource "+r);
if (!r.isDirectory())
throw new IllegalArgumentException("Not directory webapps resource "+r);
if(Attributes != null) {
if(((Attributes.length / 2) * 2) != Attributes.length) {
throw new IllegalArgumentException("Attributes must be in pairs of key,value.");
}
}
String[] files=r.list();
for (int f=0;files!=null && f<files.length;f++)
{
String context=files[f];
if (context.equalsIgnoreCase("CVS/") ||
context.equalsIgnoreCase("CVS") ||
context.startsWith("."))
continue;
String app = r.addPath(r.encode(files[f])).toString();
if (context.toLowerCase().endsWith(".war") ||
context.toLowerCase().endsWith(".jar"))
{
context=context.substring(0,context.length()-4);
Resource unpacked=r.addPath(context);
if (unpacked!=null && unpacked.exists() && unpacked.isDirectory())
continue;
}
if (_rootWebApp!=null && (context.equals(_rootWebApp)||context.equals(_rootWebApp+"/")))
context="/";
else
context="/"+context;
WebApplicationContext wac= addWebApplication(host,
context,
app);
wac.setExtractWAR(extract);
wac.setClassLoaderJava2Compliant(java2CompliantClassLoader);
if (defaults!=null)
{
if (defaults.length()==0)
wac.setDefaultsDescriptor(null);
else
wac.setDefaultsDescriptor(defaults);
}
if(Attributes != null) {
for(int i = 0; i < Attributes.length; i++, i++) {
wac.setAttribute(Attributes[i],Attributes[i + 1]);
}
}
wacs.add(wac);
}
return (WebApplicationContext[])wacs.toArray(new WebApplicationContext[wacs.size()]);
}
/* ------------------------------------------------------------ */
/** setWebApplicationConfigurationClasses
* Set up the list of classnames of WebApplicationContext.Configuration
* implementations that will be applied to configure every webapp.
* The list can be overridden by individual WebApplicationContexts.
* @param configurationClasses
*/
public void setWebApplicationConfigurationClassNames (String[] configurationClassNames)
{
if (configurationClassNames != null)
{
_webAppConfigurationClassNames = new String[configurationClassNames.length];
System.arraycopy(configurationClassNames, 0, _webAppConfigurationClassNames, 0, configurationClassNames.length);
}
}
public String[] getWebApplicationConfigurationClassNames ()
{
return _webAppConfigurationClassNames;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public static void main(String[] arg)
{
String[] dftConfig={"etc/jetty.xml"};
if (arg.length==0)
{
log.info("Using default configuration: etc/jetty.xml");
arg=dftConfig;
}
final Server[] servers=new Server[arg.length];
// create and start the servers.
for (int i=0;i<arg.length;i++)
{
try
{
servers[i] = new Server(arg[i]);
servers[i].setStopAtShutdown(true);
servers[i].start();
}
catch(Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
}
}
// create and start the servers.
for (int i=0;i<arg.length;i++)
{
try{servers[i].join();}
catch (Exception e){LogSupport.ignore(log,e);}
}
}
/**
* ShutdownHook thread for stopping all servers.
*
* Thread is hooked first time list of servers is changed.
*/
private static class ShutdownHookThread extends Thread {
private boolean hooked = false;
private ArrayList servers = new ArrayList();
/**
* Hooks this thread for shutdown.
* @see java.lang.Runtime#addShutdownHook(java.lang.Thread)
*/
private void createShutdownHook() {
if (!Boolean.getBoolean("JETTY_NO_SHUTDOWN_HOOK") && !hooked) {
try {
Method shutdownHook = java.lang.Runtime.class.getMethod("addShutdownHook",
new Class[] { java.lang.Thread.class });
shutdownHook.invoke(Runtime.getRuntime(), new Object[] { this });
this.hooked = true;
} catch (Exception e) {
if (log.isDebugEnabled()) log.debug("No shutdown hook in JVM ", e);
}
}
}
/**
* Add Server to servers list.
*/
public boolean add(Server server) {
createShutdownHook();
return this.servers.add(server);
}
/**
* Contains Server in servers list?
*/
public boolean contains(Server server) {
return this.servers.contains(server);
}
/**
* Append all Servers from Collection
*/
public boolean addAll(Collection c) {
createShutdownHook();
return this.servers.addAll(c);
}
/**
* Clear list of Servers.
*/
public void clear() {
createShutdownHook();
this.servers.clear();
}
/**
* Remove Server from list.
*/
public boolean remove(Server server) {
createShutdownHook();
return this.servers.remove(server);
}
/**
* Remove all Servers in Collection from list.
*/
public boolean removeAll(Collection c) {
createShutdownHook();
return this.servers.removeAll(c);
}
/**
* Stop all Servers in list.
*/
public void run() {
setName("Shutdown");
log.info("Shutdown hook executing");
Iterator it = servers.iterator();
while (it.hasNext()) {
Server svr = (Server) it.next();
if (svr == null) continue;
try {
svr.stop();
} catch (Exception e) {
log.warn(LogSupport.EXCEPTION, e);
}
log.info("Shutdown hook complete");
// Try to avoid JVM crash
try {
Thread.sleep(1000);
} catch (Exception e) {
log.warn(LogSupport.EXCEPTION, e);
}
}
}
}
}

View File

@ -673,6 +673,8 @@ class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener {
* Ping the specified peer, returning true if they replied to the ping within
* the timeout specified, false otherwise. This call blocks.
*
* @deprecated timeout is ignored - use I2PSocketManagerFull.ping()
* @param timeoutMs ignored
*/
public boolean ping(Destination peer, long timeoutMs) {
try {

View File

@ -0,0 +1,17 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
# zzz - public domain
#
## launching sh.exe with -login parameter will open a shell with the current path always pointing to \bin\
## need to cd into our orignal path - where we call sh.exe from.
cd $CALLFROM
## echo $PWD
## except this everything is the same with bundle-message.sh
## walking - public domain :-D
source bundle-messages.sh $PARAS

View File

@ -73,11 +73,44 @@
<delete dir="./tmpextract" />
<ant target="war" />
<!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="false" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
</exec>
<!-- jar again to get the latest messages_*.class files -->
<jar destfile="./build/routerconsole.jar" basedir="./build/obj" includes="**/*.class" update="true" />
</target>
<target name="poupdate" depends="build">
<ant target="war" />
<!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="cmd" osfamily="windows" failifexecutionfails="true" >
<arg value="/c" />
<arg value="bundle-messages.bat" />
<arg value="-p" />
</exec>
</target>
<target name="war" depends="precompilejsp">
<!-- Don't include the css in the war, the main build.xml will copy it to docs/themes/console/ -->
<war destfile="build/routerconsole.war" webxml="../jsp/web-out.xml"
basedir="../jsp/" excludes="web.xml, *.css, *.java, *.jsp, web-fragment.xml">
basedir="../jsp/" excludes="web.xml, *.css, **/*.java, *.jsp, *.jsi, web-fragment.xml">
</war>
</target>
<target name="precompilejsp" unless="precompilejsp.uptodate">
@ -86,7 +119,36 @@
<delete file="../jsp/web-out.xml" />
<mkdir dir="../jsp/WEB-INF/" />
<mkdir dir="../jsp/WEB-INF/classes" />
<!-- there are various jspc ant tasks, but they all seem a bit flakey -->
<!--
** Usage: jspc <options> <jsp files>
** where jsp files is
** -webapp <dir> A directory containing a web-app, whose JSP pages
** will be processed recursively
** or any number of
** <file> A file to be parsed as a JSP page
** where options include:
** -help Print this help message
** -v Verbose mode
** -d <dir> Output Directory (default -Djava.io.tmpdir)
** -l Outputs the name of the JSP page upon failure
** -s Outputs the name of the JSP page upon success
** -p <name> Name of target package (default org.apache.jsp)
** -c <name> Name of target class name (only applies to first JSP page)
** -mapped Generates separate write() calls for each HTML line in the JSP
** -die[#] Generates an error return code (#) on fatal errors (default 1)
** -uribase <dir> The uri directory compilations should be relative to
** (default "/")
** -uriroot <dir> Same as -webapp
** -compile Compiles generated servlets
** -webinc <file> Creates a partial servlet mappings in the file
** -webxml <file> Creates a complete web.xml in the file
** -ieplugin <clsid> Java Plugin classid for Internet Explorer
** -classpath <path> Overrides java.class.path system property
** -xpoweredBy Add X-Powered-By response header
** -trimSpaces Trim spaces in template text between actions, directives
-->
<java classname="org.apache.jasper.JspC" fork="true" failonerror="true">
<classpath>
<pathelement location="../../jetty/jettylib/jasper-compiler.jar" />
@ -115,6 +177,7 @@
</java>
<javac debug="true" deprecation="on" source="1.5" target="1.5"
encoding="UTF-8"
destdir="../jsp/WEB-INF/classes/"
srcdir="../jsp/WEB-INF/classes" includes="**/*.java">
<compilerarg line="${javac.compilerargs}" />
@ -133,10 +196,13 @@
<pathelement location="../../../core/java/build/i2p.jar" />
</classpath>
</javac>
<!-- save these so we can run gettext on the generated java files later
<delete>
<fileset dir="../jsp/WEB-INF/" includes="**/*.java" />
<fileset dir="../jsp/WEB-INF/" includes="**/*.jsp" />
</delete>
-->
<copy file="../jsp/web.xml" tofile="../jsp/web-out.xml" />
<loadfile property="jspc.web.fragment" srcfile="../jsp/web-fragment.xml" />
<replace file="../jsp/web-out.xml">

View File

@ -0,0 +1,26 @@
@echo off
set Callfrom=%cd%
set Paras=%1
rem before calling make sure you have msys and mingw 's "bin" path
rem in your current searching path
rem type "set path" to check
if not exist ..\locale\*.only goto updateALL
rem put a messages_xx.only(eg messages_zh.only) into locale folder
rem this script will only touch the po file(eg zh) you specified, leaving other po files untact.
for %%i in (..\locale\*.only) do set PO=%%~ni
echo [Notice] Yu choose to Ony update the choosen file: %PO%.po
for %%i in (..\locale\*.po) do if not %%~ni==%PO% ren %%i %%~ni.po-
call sh --login %cd%\bmsg.sh
for %%i in (..\locale\*.po-) do if not %%~ni==%PO% ren %%i %%~ni.po
goto end
:updateALL
call sh --login %cd%\bmsg.sh
:end
echo End of Message Bundling

View File

@ -0,0 +1,116 @@
#
# Update messages_xx.po and messages_xx.class files,
# from both java and jsp sources.
# Requires installed programs xgettext, msgfmt, msgmerge, and find.
#
# usage:
# bundle-messages.sh (generates the resource bundle from the .po file)
# bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle)
#
# zzz - public domain
#
CLASS=net.i2p.router.web.messages
TMPFILE=build/javafiles.txt
export TZ=UTC
if [ "$1" = "-p" ]
then
POUPDATE=1
fi
#
# generate strings/Countries.java from ../../../installer/resources/countries.txt
#
CFILE=../../../installer/resources/countries.txt
# add ../java/ so the refs will work in the po file
JFILE=../java/build/Countries.java
if [ $CFILE -nt $JFILE -o ! -s $JFILE ]
then
mkdir -p build
echo '// Automatically generated pseudo-java for xgettext - do not edit' > $JFILE
echo '// Translators may wish to translate a few of these, do not bother to translate all of them!!' >> $JFILE
sed 's/..,\(..*\)/_("\1");/' $CFILE >> $JFILE
fi
# list specific files in router/ here, so we don't scan the whole tree
ROUTERFILES="\
../../../router/java/src/net/i2p/router/RouterThrottleImpl.java \
../../../router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java \
../../../router/java/src/net/i2p/router/transport/TransportManager.java \
../../../router/java/src/net/i2p/router/transport/GetBidsJob.java \
../../../router/java/src/net/i2p/router/Blocklist.java \
../../../router/java/src/net/i2p/router/transport/ntcp/EstablishState.java"
# add ../java/ so the refs will work in the po file
JPATHS="../java/src ../jsp/WEB-INF ../java/strings $JFILE $ROUTERFILES"
for i in ../locale/messages_*.po
do
# get language
LG=${i#../locale/messages_}
LG=${LG%.po}
if [ "$POUPDATE" = "1" ]
then
# make list of java files newer than the .po file
find $JPATHS -name *.java -newer $i > $TMPFILE
fi
if [ -s build/obj/net/i2p/router/web/messages_$LG.class -a \
build/obj/net/i2p/router/web/messages_$LG.class -nt $i -a \
! -s $TMPFILE ]
then
continue
fi
if [ "$POUPDATE" = "1" ]
then
echo "Updating the $i file from the tags..."
# extract strings from java and jsp files, and update messages.po files
# translate calls must be one of the forms:
# _("foo")
# _x("foo")
# intl._("foo")
# intl.title("foo")
# handler._("foo")
# formhandler._("foo")
# net.i2p.router.web.Messages.getString("foo")
# In a jsp, you must use a helper or handler that has the context set.
# To start a new translation, copy the header from an old translation to the new .po file,
# then ant distclean updater.
find $JPATHS -name *.java > $TMPFILE
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 \
--keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
--keyword=handler._ --keyword=formhandler._ \
--keyword=net.i2p.router.web.Messages.getString \
-o ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - xgettext failed, not updating translations'
rm -f ${i}t
break
fi
msgmerge -U --backup=none $i ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - msgmerge failed, not updating translations'
rm -f ${i}t
break
fi
rm -f ${i}t
# so we don't do this again
touch $i
fi
echo "Generating ${CLASS}_$LG ResourceBundle..."
# convert to class files in build/obj
msgfmt --java --statistics -r $CLASS -l $LG -d build/obj $i
if [ $? -ne 0 ]
then
echo 'Warning - msgfmt failed, not updating translations'
break
fi
done
rm -f $TMPFILE
# todo: return failure
exit 0

View File

@ -11,6 +11,8 @@ public class CSSHelper extends HelperBase {
public static final String DEFAULT_THEME = "light";
private static final String BASE = "/themes/console/";
private static final String FORCE = "classic";
public static final String PROP_REFRESH = "routerconsole.summaryRefresh";
public static final String DEFAULT_REFRESH = "60";
public String getTheme(String userAgent) {
String url = BASE;
@ -22,4 +24,37 @@ public class CSSHelper extends HelperBase {
}
return url;
}
/** change default language for the router but don't save it */
public void setLang(String lang) {
if (lang != null && lang.length() > 0)
_context.router().setConfigSetting(Messages.PROP_LANG, lang);
}
/** needed for conditional css loads for zh */
public String getLang() {
return Messages.getLanguage(_context);
}
/** change refresh and save it */
public void setRefresh(String r) {
_context.router().setConfigSetting(PROP_REFRESH, r);
_context.router().saveConfig();
}
/** @return refresh time in seconds, as a string */
public String getRefresh() {
return _context.getProperty(PROP_REFRESH, DEFAULT_REFRESH);
}
/** translate the title and display consistently */
public String title(String s) {
StringBuilder buf = new StringBuilder(128);
buf.append("<title>")
.append(_("I2P Router Console"))
.append(" - ")
.append(_(s))
.append("</title>");
return buf.toString();
}
}

View File

@ -13,7 +13,7 @@ import java.util.Iterator;
*
*/
public class ConfigAdvancedHandler extends FormHandler {
private boolean _forceRestart;
//private boolean _forceRestart;
private boolean _shouldSave;
private String _config;
@ -27,7 +27,7 @@ public class ConfigAdvancedHandler extends FormHandler {
}
public void setShouldsave(String moo) { _shouldSave = true; }
public void setRestart(String moo) { _forceRestart = true; }
//public void setRestart(String moo) { _forceRestart = true; }
public void setConfig(String val) {
_config = val;
@ -54,7 +54,7 @@ public class ConfigAdvancedHandler extends FormHandler {
unsetKeys.remove(key);
}
} catch (IOException ioe) {
addFormError("Error updating the configuration (IOERROR) - please see the error logs");
addFormError(_("Error updating the configuration - please see the error logs"));
return;
}
@ -66,15 +66,15 @@ public class ConfigAdvancedHandler extends FormHandler {
boolean saved = _context.router().saveConfig();
if (saved)
addFormNotice("Configuration saved successfully");
addFormNotice(_("Configuration saved successfully"));
else
addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs");
addFormNotice(_("Error saving the configuration (applied but not saved) - please see the error logs"));
if (_forceRestart) {
addFormNotice("Performing a soft restart");
_context.router().restart();
addFormNotice("Soft restart complete");
}
//if (_forceRestart) {
// addFormNotice("Performing a soft restart");
// _context.router().restart();
// addFormNotice("Soft restart complete");
//}
}
}
}

View File

@ -29,11 +29,16 @@ public class ConfigClientsHandler extends FormHandler {
@Override
protected void processForm() {
if (_action.startsWith("Save Client")) {
if (_action.equals(_("Save Client Configuration"))) {
saveClientChanges();
} else if (_action.startsWith("Save WebApp")) {
return;
}
if (_action.equals(_("Save WebApp Configuration"))) {
saveWebAppChanges();
} else if (_action.startsWith("Start ")) {
return;
}
// value
if (_action.startsWith("Start ")) {
String app = _action.substring(6);
int appnum = -1;
try {
@ -43,10 +48,26 @@ public class ConfigClientsHandler extends FormHandler {
startClient(appnum);
else
startWebApp(app);
} else if (_action.toLowerCase().startsWith("start<span class=hide> ") &&
return;
}
// value
if (_action.startsWith("Delete ")) {
String app = _action.substring(7);
int appnum = -1;
try {
appnum = Integer.parseInt(app);
} catch (NumberFormatException nfe) {}
if (appnum >= 0)
deleteClient(appnum);
return;
}
// label (IE)
String xStart = _("Start");
if (_action.toLowerCase().startsWith(xStart + "<span class=hide> ") &&
_action.toLowerCase().endsWith("</span>")) {
// IE sucks
String app = _action.substring(23, _action.length() - 7);
String app = _action.substring(xStart.length() + 18, _action.length() - 7);
int appnum = -1;
try {
appnum = Integer.parseInt(app);
@ -56,33 +77,86 @@ public class ConfigClientsHandler extends FormHandler {
else
startWebApp(app);
} else {
addFormError("Unsupported " + _action + ".");
addFormError(_("Unsupported") + ' ' + _action + '.');
}
}
public void setSettings(Map settings) { _settings = new HashMap(settings); }
private void saveClientChanges() {
List clients = ClientAppConfig.getClientApps(_context);
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(_context);
for (int cur = 0; cur < clients.size(); cur++) {
ClientAppConfig ca = (ClientAppConfig) clients.get(cur);
ClientAppConfig ca = clients.get(cur);
Object val = _settings.get(cur + ".enabled");
if (! "webConsole".equals(ca.clientName))
if (! ("webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName)))
ca.disabled = val == null;
// edit of an existing entry
String desc = getString("desc" + cur);
if (desc != null) {
int spc = desc.indexOf(" ");
String clss = desc;
String args = null;
if (spc >= 0) {
clss = desc.substring(0, spc);
args = desc.substring(spc + 1);
}
ca.className = clss;
ca.args = args;
ca.clientName = getString("name" + cur);
}
}
int newClient = clients.size();
String newDesc = getString("desc" + newClient);
if (newDesc != null && newDesc.trim().length() > 0) {
// new entry
int spc = newDesc.indexOf(" ");
String clss = newDesc;
String args = null;
if (spc >= 0) {
clss = newDesc.substring(0, spc);
args = newDesc.substring(spc + 1);
}
String name = getString("name" + newClient);
if (name == null || name.trim().length() <= 0) name = "new client";
ClientAppConfig ca = new ClientAppConfig(clss, name, args, 2*60*1000,
_settings.get(newClient + ".enabled") != null);
clients.add(ca);
addFormNotice(_("New client added") + ": " + name + " (" + clss + ").");
}
ClientAppConfig.writeClientAppConfig(_context, clients);
addFormNotice("Client configuration saved successfully - restart required to take effect.");
addFormNotice(_("Client configuration saved successfully - restart required to take effect."));
}
/** curses Jetty for returning arrays */
private String getString(String key) {
String[] arr = (String[]) _settings.get(key);
if (arr == null)
return null;
return arr[0];
}
private void startClient(int i) {
List clients = ClientAppConfig.getClientApps(_context);
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(_context);
if (i >= clients.size()) {
addFormError("Bad client index.");
addFormError(_("Bad client index."));
return;
}
ClientAppConfig ca = (ClientAppConfig) clients.get(i);
ClientAppConfig ca = clients.get(i);
LoadClientAppsJob.runClient(ca.className, ca.clientName, LoadClientAppsJob.parseArgs(ca.args), configClient_log);
addFormNotice("Client " + ca.clientName + " started.");
addFormNotice(_("Client") + ' ' + _(ca.clientName) + ' ' + _("started") + '.');
}
private void deleteClient(int i) {
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(_context);
if (i < 0 || i >= clients.size()) {
addFormError(_("Bad client index."));
return;
}
ClientAppConfig ca = clients.remove(i);
ClientAppConfig.writeClientAppConfig(_context, clients);
addFormNotice(_("Client") + ' ' + _(ca.clientName) + ' ' + _("deleted") + '.');
}
private void saveWebAppChanges() {
@ -99,7 +173,7 @@ public class ConfigClientsHandler extends FormHandler {
props.setProperty(name, "" + (val != null));
}
RouterConsoleRunner.storeWebAppProperties(props);
addFormNotice("WebApp configuration saved successfully - restart required to take effect.");
addFormNotice(_("WebApp configuration saved successfully - restart required to take effect."));
}
// Big hack for the moment, not using properties for directory and port
@ -117,14 +191,14 @@ public class ConfigClientsHandler extends FormHandler {
path = new File(path, app + ".war");
s.addWebApplication("/"+ app, path.getAbsolutePath()).start();
// no passwords... initialize(wac);
addFormNotice("WebApp <a href=\"/" + app + "/\">" + app + "</a> started.");
addFormNotice(_("WebApp") + " <a href=\"/" + app + "/\">" + _(app) + "</a> " + _("started") + '.');
} catch (Exception ioe) {
addFormError("Failed to start " + app + " " + ioe + ".");
addFormError(_("Failed to start") + ' ' + _(app) + " " + ioe + '.');
}
return;
}
}
}
addFormError("Failed to find server.");
addFormError(_("Failed to find server."));
}
}

View File

@ -9,20 +9,42 @@ import java.util.TreeSet;
import net.i2p.router.startup.ClientAppConfig;
public class ConfigClientsHelper extends HelperBase {
private String _edit;
public ConfigClientsHelper() {}
public void setEdit(String edit) {
if (edit == null)
return;
String xStart = _("Edit");
if (edit.startsWith(xStart + "<span class=hide> ") &&
edit.endsWith("</span>")) {
// IE sucks
_edit = edit.substring(xStart.length() + 18, edit.length() - 7);
} else if (edit.startsWith("Edit ")) {
_edit = edit.substring(5);
} else if (edit.startsWith(xStart + ' ')) {
_edit = edit.substring(xStart.length() + 1);
} else if ((_("Add Client")).equals(edit)) {
_edit = "new";
}
}
public String getForm1() {
StringBuilder buf = new StringBuilder(1024);
buf.append("<table>\n");
buf.append("<tr><th align=\"right\">Client</th><th>Run at Startup?</th><th>Start Now</th><th align=\"left\">Class and arguments</th></tr>\n");
buf.append("<tr><th align=\"right\">" + _("Client") + "</th><th>" + _("Run at Startup?") + "</th><th>" + _("Start Now") + "</th><th align=\"left\">" + _("Class and arguments") + "</th></tr>\n");
List clients = ClientAppConfig.getClientApps(_context);
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(_context);
for (int cur = 0; cur < clients.size(); cur++) {
ClientAppConfig ca = (ClientAppConfig) clients.get(cur);
renderForm(buf, ""+cur, ca.clientName, false, !ca.disabled, "webConsole".equals(ca.clientName),
ca.className + ((ca.args != null) ? " " + ca.args : ""));
ClientAppConfig ca = clients.get(cur);
renderForm(buf, ""+cur, ca.clientName, false, !ca.disabled,
"webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName),
ca.className + ((ca.args != null) ? " " + ca.args : ""), (""+cur).equals(_edit), true);
}
if ("new".equals(_edit))
renderForm(buf, "" + clients.size(), "", false, false, false, "", true, false);
buf.append("</table>\n");
return buf.toString();
}
@ -30,30 +52,39 @@ public class ConfigClientsHelper extends HelperBase {
public String getForm2() {
StringBuilder buf = new StringBuilder(1024);
buf.append("<table>\n");
buf.append("<tr><th align=\"right\">WebApp</th><th>Run at Startup?</th><th>Start Now</th><th align=\"left\">Description</th></tr>\n");
buf.append("<tr><th align=\"right\">" + _("WebApp") + "</th><th>" + _("Run at Startup?") + "</th><th>" + _("Start Now") + "</th><th align=\"left\">" + _("Description") + "</th></tr>\n");
Properties props = RouterConsoleRunner.webAppProperties();
Set keys = new TreeSet(props.keySet());
for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
Set<String> keys = new TreeSet(props.keySet());
for (Iterator<String> iter = keys.iterator(); iter.hasNext(); ) {
String name = iter.next();
if (name.startsWith(RouterConsoleRunner.PREFIX) && name.endsWith(RouterConsoleRunner.ENABLED)) {
String app = name.substring(RouterConsoleRunner.PREFIX.length(), name.lastIndexOf(RouterConsoleRunner.ENABLED));
String val = props.getProperty(name);
renderForm(buf, app, app, !"addressbook".equals(app), "true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war");
renderForm(buf, app, app, !"addressbook".equals(app),
"true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war", false, false);
}
}
buf.append("</table>\n");
return buf.toString();
}
private void renderForm(StringBuilder buf, String index, String name, boolean urlify, boolean enabled, boolean ro, String desc) {
/** ro trumps edit and showEditButton */
private void renderForm(StringBuilder buf, String index, String name, boolean urlify,
boolean enabled, boolean ro, String desc, boolean edit, boolean showEditButton) {
buf.append("<tr><td class=\"mediumtags\" align=\"right\" width=\"25%\">");
if (urlify && enabled) {
String link = "/";
if (! RouterConsoleRunner.ROUTERCONSOLE.equals(name))
link += name + "/";
buf.append("<a href=\"").append(link).append("\">").append(name).append("</a>");
buf.append("<a href=\"").append(link).append("\">").append(_(name)).append("</a>");
} else if (edit && !ro) {
buf.append("<input type=\"text\" name=\"name").append(index).append("\" value=\"");
if (name.length() > 0)
buf.append(_(name));
buf.append("\" >");
} else {
buf.append(name);
if (name.length() > 0)
buf.append(_(name));
}
buf.append("</td><td align=\"center\" width=\"10%\"><input type=\"checkbox\" class=\"optbox\" name=\"").append(index).append(".enabled\" value=\"true\" ");
if (enabled) {
@ -62,9 +93,21 @@ public class ConfigClientsHelper extends HelperBase {
buf.append("disabled=\"true\" ");
}
buf.append("/></td><td align=\"center\" width=\"15%\">");
if (!enabled) {
buf.append("<button type=\"submit\" name=\"action\" value=\"Start ").append(index).append("\" >Start<span class=hide> ").append(index).append("</span></button>");
if ((!enabled) && !edit) {
buf.append("<button type=\"submit\" name=\"action\" value=\"Start ").append(index).append("\" >" + _("Start") + "<span class=hide> ").append(index).append("</span></button>");
}
buf.append("</td><td align=\"left\" width=\"50%\">").append(desc).append("</td></tr>\n");
if (showEditButton && (!edit) && !ro) {
buf.append("<button type=\"submit\" name=\"edit\" value=\"Edit ").append(index).append("\" >" + _("Edit") + "<span class=hide> ").append(index).append("</span></button>");
buf.append("<button type=\"submit\" name=\"action\" value=\"Delete ").append(index).append("\" >" + _("Delete") + "<span class=hide> ").append(index).append("</span></button>");
}
buf.append("</td><td align=\"left\" width=\"50%\">");
if (edit && !ro) {
buf.append("<input type=\"text\" size=\"80\" name=\"desc").append(index).append("\" value=\"");
buf.append(desc);
buf.append("\" >");
} else {
buf.append(desc);
}
buf.append("</td></tr>\n");
}
}

View File

@ -15,12 +15,12 @@ public class ConfigKeyringHandler extends FormHandler {
@Override
protected void processForm() {
if (_action == null) return;
boolean adding = _action.startsWith("Add");
if (adding || _action.startsWith("Delete")) {
boolean adding = _action.equals(_("Add key"));
if (adding || _action.equals(_("Delete key"))) {
if (_peer == null)
addFormError("You must enter a destination");
addFormError(_("You must enter a destination"));
if (_key == null && adding)
addFormError("You must enter a key");
addFormError(_("You must enter a key"));
if (_peer == null || (_key == null && adding))
return;
Hash h = ConvertToHash.getHash(_peer);
@ -31,22 +31,22 @@ public class ConfigKeyringHandler extends FormHandler {
} catch (DataFormatException dfe) {}
if (h != null && h.getData() != null && sk.getData() != null) {
_context.keyRing().put(h, sk);
addFormNotice("Key for " + h.toBase64() + " added to keyring");
addFormNotice(_("Key for") + " " + h.toBase64() + " " + _("added to keyring"));
} else {
addFormError("Invalid destination or key");
addFormError(_("Invalid destination or key"));
}
} else { // Delete
if (h != null && h.getData() != null) {
if (_context.keyRing().remove(h) != null)
addFormNotice("Key for " + h.toBase64() + " removed from keyring");
addFormNotice(_("Key for") + " " + h.toBase64() + " " + _("removed from keyring"));
else
addFormNotice("Key for " + h.toBase64() + " not found in keyring");
addFormNotice(_("Key for") + " " + h.toBase64() + " " + _("not found in keyring"));
} else {
addFormError("Invalid destination");
addFormError(_("Invalid destination"));
}
}
} else {
addFormError("Unsupported");
addFormError(_("Unsupported"));
}
}

View File

@ -36,42 +36,33 @@ public class ConfigLoggingHelper extends HelperBase {
sortedLogs.add(prefix);
}
buf.append("<textarea name=\"levels\" rows=\"4\" cols=\"60\">");
buf.append("<textarea name=\"levels\" rows=\"4\" cols=\"60\" wrap=\"off\">");
for (Iterator iter = sortedLogs.iterator(); iter.hasNext(); ) {
String prefix = (String)iter.next();
String level = limits.getProperty(prefix);
buf.append(prefix).append('=').append(level).append('\n');
}
buf.append("</textarea><br>\n");
buf.append("<i>Add additional logging statements above. Example: net.i2p.router.tunnel=WARN</i><br>");
buf.append("<i>Or put entries in the logger.config file. Example: logger.record.net.i2p.router.tunnel=WARN</i><br>");
buf.append("<i>Valid levels are DEBUG, INFO, WARN, ERROR, CRIT</i>\n");
buf.append("<i>" + _("Add additional logging statements above. Example: net.i2p.router.tunnel=WARN") + "</i><br>");
buf.append("<i>" + _("Or put entries in the logger.config file. Example: logger.record.net.i2p.router.tunnel=WARN") + "</i><br>");
buf.append("<i>" + _("Valid levels are DEBUG, INFO, WARN, ERROR, CRIT") + "</i>\n");
return buf.toString();
}
private static String[] levels = { _x("CRIT"), _x("ERROR"), _x("WARN"), _x("INFO"), _x("DEBUG") };
public String getDefaultLogLevelBox() {
String cur = _context.logManager().getDefaultLimit();
StringBuilder buf = new StringBuilder(128);
buf.append("<select name=\"defaultloglevel\">\n");
buf.append("<option value=\"DEBUG\" ");
if ("DEBUG".equals(cur)) buf.append(" selected=\"true\" ");
buf.append(">DEBUG</option>\n");
buf.append("<option value=\"INFO\" ");
if ("INFO".equals(cur)) buf.append(" selected=\"true\" ");
buf.append(">INFO</option>\n");
buf.append("<option value=\"WARN\" ");
if ("WARN".equals(cur)) buf.append(" selected=\"true\" ");
buf.append(">WARN</option>\n");
buf.append("<option value=\"ERROR\" ");
if ("ERROR".equals(cur)) buf.append(" selected=\"true\" ");
buf.append(">ERROR</option>\n");
buf.append("<option value=\"CRIT\" ");
if ("CRIT".equals(cur)) buf.append(" selected=\"true\" ");
buf.append(">CRIT</option>\n");
for (int i = 0; i < levels.length; i++) {
String l = levels[i];
buf.append("<option value=\"").append(l).append("\" ");
if (l.equals(cur))
buf.append(" selected=\"true\" ");
buf.append('>').append(_(l)).append("</option>\n");
}
buf.append("</select>\n");
return buf.toString();

View File

@ -0,0 +1,38 @@
package net.i2p.router.web;
import java.io.IOException;
/**
* refactored from confignav.jsp to reduce size and make translation easier
* @author zzz
*/
public class ConfigNavHelper extends HelperBase {
/** configX.jsp */
private static final String pages[] =
{"", "ui", "service", "update", "tunnels",
"clients", "peer", "keyring", "logging", "stats",
"advanced" };
private static final String titles[] =
{_x("Network"), _x("UI"), _x("Service"), _x("Update"), _x("Tunnels"),
_x("Clients"), _x("Peers"), _x("Keyring"), _x("Logging"), _x("Stats"),
_x("Advanced") };
public void renderNavBar(String requestURI) throws IOException {
StringBuilder buf = new StringBuilder(1024);
for (int i = 0; i < pages.length; i++) {
String page = "config" + pages[i] + ".jsp";
if (requestURI.indexOf(page) != -1) {
// we are there
buf.append(_(titles[i]));
} else {
// we are not there, make a link
buf.append("<a href=\"").append(page).append("\">").append(_(titles[i])).append("</a>");
}
if (i != pages.length - 1)
buf.append(" |\n");
}
_out.write(buf.toString());
}
}

View File

@ -4,7 +4,7 @@ import net.i2p.router.Router;
import net.i2p.router.transport.FIFOBandwidthRefiller;
import net.i2p.router.transport.TransportManager;
import net.i2p.router.transport.udp.UDPTransport;
import net.i2p.router.web.ConfigServiceHandler.UpdateWrapperManagerAndRekeyTask;
import net.i2p.router.web.ConfigServiceHandler;
/**
* Handler to deal with form submissions from the main config form and act
@ -30,6 +30,7 @@ public class ConfigNetHandler extends FormHandler {
private String _ntcpAutoIP;
private boolean _ntcpAutoPort;
private boolean _upnp;
private boolean _laptop;
private String _inboundRate;
private String _inboundBurstRate;
private String _inboundBurst;
@ -44,7 +45,7 @@ public class ConfigNetHandler extends FormHandler {
@Override
protected void processForm() {
if (_saveRequested || ( (_action != null) && ("Save changes".equals(_action)) )) {
if (_saveRequested || ( (_action != null) && (_("Save changes").equals(_action)) )) {
saveChanges();
} else if (_recheckReachabilityRequested) {
recheckReachability();
@ -70,6 +71,7 @@ public class ConfigNetHandler extends FormHandler {
_ntcpAutoPort = mode.equals("2");
}
public void setUpnp(String moo) { _upnp = true; }
public void setLaptop(String moo) { _laptop = true; }
public void setHostname(String hostname) {
_hostname = (hostname != null ? hostname.trim() : null);
@ -116,7 +118,7 @@ public class ConfigNetHandler extends FormHandler {
private void recheckReachability() {
_context.commSystem().recheckReachability();
addFormNotice("Rechecking router reachability...");
addFormNotice(_("Rechecking router reachability..."));
}
/**
@ -145,7 +147,7 @@ public class ConfigNetHandler extends FormHandler {
// Todo: Catch local IPs right here rather than complaining later
_context.router().setConfigSetting(UDPTransport.PROP_EXTERNAL_HOST, uhost);
if ((!oldUdp.equals(_udpAutoIP)) || (!oldUHost.equals(uhost))) {
addFormNotice("Updating IP address");
addFormNotice(_("Updating IP address"));
restartRequired = true;
}
}
@ -163,17 +165,17 @@ public class ConfigNetHandler extends FormHandler {
if ((!oldAutoHost.equals(_ntcpAutoIP)) || ! oldNHost.equalsIgnoreCase(_ntcpHostname)) {
if ("disabled".equals(_ntcpAutoIP)) {
addFormNotice("Disabling TCP completely");
addFormNotice(_("Disabling TCP completely"));
} else if ("false".equals(_ntcpAutoIP) && _ntcpHostname.length() > 0) {
// Todo: Catch local IPs right here rather than complaining later
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME, _ntcpHostname);
addFormNotice("Updating inbound TCP address to " + _ntcpHostname);
addFormNotice(_("Updating inbound TCP address to") + " " + _ntcpHostname);
} else {
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME);
if ("false".equals(_ntcpAutoIP))
addFormNotice("Disabling inbound TCP");
addFormNotice(_("Disabling inbound TCP"));
else
addFormNotice("Updating inbound TCP address to auto"); // true or always
addFormNotice(_("Updating inbound TCP address to auto")); // true or always
}
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_IP, _ntcpAutoIP);
_context.router().setConfigSetting(TransportManager.PROP_ENABLE_NTCP, "" + !"disabled".equals(_ntcpAutoIP));
@ -182,10 +184,10 @@ public class ConfigNetHandler extends FormHandler {
if (oldAutoPort != _ntcpAutoPort || ! oldNPort.equals(_ntcpPort)) {
if (_ntcpPort.length() > 0 && !_ntcpAutoPort) {
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT, _ntcpPort);
addFormNotice("Updating inbound TCP port to " + _ntcpPort);
addFormNotice(_("Updating inbound TCP port to") + " " + _ntcpPort);
} else {
_context.router().removeConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_PORT);
addFormNotice("Updating inbound TCP port to auto");
addFormNotice(_("Updating inbound TCP port to auto"));
}
_context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_AUTO_PORT, "" + _ntcpAutoPort);
restartRequired = true;
@ -197,7 +199,7 @@ public class ConfigNetHandler extends FormHandler {
if (!oldPort.equals(_udpPort)) {
_context.router().setConfigSetting(UDPTransport.PROP_INTERNAL_PORT, _udpPort);
_context.router().setConfigSetting(UDPTransport.PROP_EXTERNAL_PORT, _udpPort);
addFormNotice("Updating UDP port from " + oldPort + " to " + _udpPort);
addFormNotice(_("Updating UDP port from") + " " + oldPort + " " + _("to") + " " + _udpPort);
restartRequired = true;
}
}
@ -213,9 +215,9 @@ public class ConfigNetHandler extends FormHandler {
if (switchRequired) {
_context.router().setConfigSetting(PROP_HIDDEN, "" + _hiddenMode);
if (_hiddenMode)
addFormError("Gracefully restarting into Hidden Router Mode");
addFormError(_("Gracefully restarting into Hidden Router Mode"));
else
addFormError("Gracefully restarting to exit Hidden Router Mode");
addFormError(_("Gracefully restarting to exit Hidden Router Mode"));
}
_context.router().setConfigSetting(Router.PROP_DYNAMIC_KEYS, "" + _dynamicKeys);
@ -224,15 +226,25 @@ public class ConfigNetHandler extends FormHandler {
_upnp) {
// This is minor, don't set restartRequired
if (_upnp)
addFormNotice("Enabling UPnP, restart required to take effect");
addFormNotice(_("Enabling UPnP, restart required to take effect"));
else
addFormNotice("Disabling UPnP, restart required to take effect");
addFormNotice(_("Disabling UPnP, restart required to take effect"));
}
_context.router().setConfigSetting(TransportManager.PROP_ENABLE_UPNP, "" + _upnp);
if (Boolean.valueOf(_context.getProperty(UDPTransport.PROP_LAPTOP_MODE)).booleanValue() !=
_laptop) {
// This is minor, don't set restartRequired
if (_laptop)
addFormNotice(_("Enabling laptop mode"));
else
addFormNotice(_("Disabling laptop mode"));
}
_context.router().setConfigSetting(UDPTransport.PROP_LAPTOP_MODE, "" + _laptop);
if (_requireIntroductions) {
_context.router().setConfigSetting(UDPTransport.PROP_FORCE_INTRODUCERS, "true");
addFormNotice("Requiring SSU introduers");
addFormNotice(_("Requiring SSU introducers"));
} else {
_context.router().removeConfigSetting(UDPTransport.PROP_FORCE_INTRODUCERS);
}
@ -246,40 +258,43 @@ public class ConfigNetHandler extends FormHandler {
}
boolean saved = _context.router().saveConfig();
if ( (_action != null) && ("Save changes".equals(_action)) ) {
if ( (_action != null) && (_("Save changes").equals(_action)) ) {
if (saved)
addFormNotice("Configuration saved successfully");
addFormNotice(_("Configuration saved successfully"));
else
addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs");
addFormNotice(_("Error saving the configuration (applied but not saved) - please see the error logs"));
}
if (switchRequired) {
hiddenSwitch();
} else if (restartRequired) {
// Wow this dumps all conns immediately and really isn't nice
//addFormNotice("Performing a soft restart");
//_context.router().restart();
//addFormNotice("Soft restart complete");
if (System.getProperty("wrapper.version") == null) {
// Wow this dumps all conns immediately and really isn't nice
addFormNotice("Performing a soft restart");
_context.router().restart();
addFormNotice("Soft restart complete");
// Most of the time we aren't changing addresses, just enabling or disabling
// things, so let's try just a new routerInfo and see how that works.
// Maybe we should restart if we change addresses though?
// No, this doesn't work well, really need to call SSU Transport externalAddressReceived(),
// but that's hard to get to, and doesn't handle port changes, etc.
// So don't do this...
//_context.router().rebuildRouterInfo();
//addFormNotice("Router Info rebuilt");
// There's a few changes that don't really require restart (e.g. enabling inbound TCP)
// But it would be hard to get right, so just do a restart.
addFormError("Gracefully restarting I2P to change published router address");
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
// Most of the time we aren't changing addresses, just enabling or disabling
// things, so let's try just a new routerInfo and see how that works.
// Maybe we should restart if we change addresses though?
// No, this doesn't work well, really need to call SSU Transport externalAddressReceived(),
// but that's hard to get to, and doesn't handle port changes, etc.
// So don't do this...
//_context.router().rebuildRouterInfo();
//addFormNotice("Router Info rebuilt");
} else {
// There's a few changes that don't really require restart (e.g. enabling inbound TCP)
// But it would be hard to get right, so just do a restart.
addFormError(_("Gracefully restarting I2P to change published router address"));
_context.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART));
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
}
}
}
private void hiddenSwitch() {
// Full restart required to generate new keys
_context.addShutdownTask(new UpdateWrapperManagerAndRekeyTask(Router.EXIT_GRACEFUL_RESTART));
_context.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerAndRekeyTask(Router.EXIT_GRACEFUL_RESTART));
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
}
@ -290,7 +305,7 @@ public class ConfigNetHandler extends FormHandler {
String old = _context.router().getConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE);
if ( (old == null) || (!old.equalsIgnoreCase(_sharePct)) ) {
_context.router().setConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE, _sharePct);
addFormNotice("Updating bandwidth share percentage");
addFormNotice(_("Updating bandwidth share percentage"));
updated = true;
}
}
@ -360,7 +375,7 @@ public class ConfigNetHandler extends FormHandler {
if (updated && !_ratesOnly) {
_context.bandwidthLimiter().reinitialize();
addFormNotice("Updated bandwidth limits");
addFormNotice(_("Updated bandwidth limits"));
}
}
}

View File

@ -36,7 +36,7 @@ public class ConfigNetHelper extends HelperBase {
public String getUdpAddress() {
RouterAddress addr = _context.router().getRouterInfo().getTargetAddress("SSU");
if (addr == null)
return "unknown";
return _("unknown");
UDPAddress ua = new UDPAddress(addr);
return ua.toString();
}
@ -44,20 +44,20 @@ public class ConfigNetHelper extends HelperBase {
public String getUdpIP() {
RouterAddress addr = _context.router().getRouterInfo().getTargetAddress("SSU");
if (addr == null)
return "unknown";
return _("unknown");
UDPAddress ua = new UDPAddress(addr);
if (ua.getHost() == null)
return "unknown";
return _("unknown");
return ua.getHost();
}
public String getUdpPort() {
RouterAddress addr = _context.router().getRouterInfo().getTargetAddress("SSU");
if (addr == null)
return "unknown";
return _("unknown");
UDPAddress ua = new UDPAddress(addr);
if (ua.getPort() <= 0)
return "unknown";
return _("unknown");
return "" + ua.getPort();
}
@ -84,6 +84,10 @@ public class ConfigNetHelper extends HelperBase {
return getChecked(Router.PROP_DYNAMIC_KEYS);
}
public String getLaptopChecked() {
return getChecked(UDPTransport.PROP_LAPTOP_MODE);
}
public String getTcpAutoPortChecked(int mode) {
String port = _context.getProperty(PROP_I2NP_NTCP_PORT);
boolean specified = port != null && port.length() > 0;
@ -162,7 +166,7 @@ public class ConfigNetHelper extends HelperBase {
return kbytesToBits(getShareBandwidth());
}
private String kbytesToBits(int kbytes) {
return DataHelper.formatSize(kbytes * 8 * 1024) + " bits per second";
return DataHelper.formatSize(kbytes * 8 * 1024) + ' ' + _("bits per second");
}
public String getInboundBurstRate() {
return "" + _context.bandwidthLimiter().getInboundBurstKBytesPerSecond();

View File

@ -17,26 +17,26 @@ public class ConfigPeerHandler extends FormHandler {
if ("Save Configuration".equals(_action)) {
_context.router().saveConfig();
addFormNotice("Settings saved - not really!!!!!");
} else if (_action.startsWith("Ban")) {
} else if (_action.equals(_("Ban peer until restart"))) {
Hash h = getHash();
if (h != null) {
_context.shitlist().shitlistRouterForever(h, "Manually banned via <a href=\"configpeer.jsp\">configpeer.jsp</a>");
addFormNotice("Peer " + _peer + " banned until restart");
_context.shitlist().shitlistRouterForever(h, _("Manually banned via {0}"), "<a href=\"configpeer.jsp\">configpeer.jsp</a>");
addFormNotice(_("Peer") + " " + _peer + " " + _("banned until restart") );
return;
}
addFormError("Invalid peer");
} else if (_action.startsWith("Unban")) {
addFormError(_("Invalid peer"));
} else if (_action.equals(_("Unban peer"))) {
Hash h = getHash();
if (h != null) {
if (_context.shitlist().isShitlisted(h)) {
_context.shitlist().unshitlistRouter(h);
addFormNotice("Peer " + _peer + " unbanned");
addFormNotice(_("Peer") + " " + _peer + " " + _("unbanned") );
} else
addFormNotice("Peer " + _peer + " is not currently banned");
addFormNotice(_("Peer") + " " + _peer + " " + _("is not currently banned") );
return;
}
addFormError("Invalid peer");
} else if (_action.startsWith("Adjust")) {
addFormError(_("Invalid peer"));
} else if (_action.equals(_("Adjust Profile Bonuses"))) {
Hash h = getHash();
if (h != null) {
PeerProfile prof = _context.profileOrganizer().getProfile(h);
@ -44,19 +44,19 @@ public class ConfigPeerHandler extends FormHandler {
try {
prof.setSpeedBonus(Long.parseLong(_speed));
} catch (NumberFormatException nfe) {
addFormError("Bad speed value");
addFormError(_("Bad speed value"));
}
try {
prof.setCapacityBonus(Long.parseLong(_capacity));
} catch (NumberFormatException nfe) {
addFormError("Bad capacity value");
addFormError(_("Bad capacity value"));
}
addFormNotice("Bonuses adjusted for " + _peer);
} else
addFormError("No profile exists for " + _peer);
return;
}
addFormError("Invalid peer");
addFormError(_("Invalid peer"));
} else if (_action.startsWith("Check")) {
addFormError("Unsupported");
}

View File

@ -1,7 +1,5 @@
package net.i2p.router.web;
import java.util.StringTokenizer;
import net.i2p.data.DataHelper;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
@ -11,6 +9,12 @@ import net.i2p.router.RouterContext;
*
*/
public class ConfigRestartBean {
/** all these are tagged below so no need to _x them here */
static final String[] SET1 = {"shutdownImmediate", "Shutdown immediately", "cancelShutdown", "Cancel shutdown"};
static final String[] SET2 = {"restartImmediate", "Restart immediately", "cancelShutdown", "Cancel restart"};
static final String[] SET3 = {"restart", "Restart", "shutdown", "Shutdown"};
static final String[] SET4 = {"shutdown", "Shutdown"};
public static String getNonce() {
RouterContext ctx = ContextHelper.getContext(null);
String nonce = System.getProperty("console.nonce");
@ -25,20 +29,21 @@ public class ConfigRestartBean {
String systemNonce = getNonce();
if ( (nonce != null) && (systemNonce.equals(nonce)) && (action != null) ) {
// Normal browsers send value, IE sends button label
if ("shutdownImmediate".equals(action) || "Shutdown immediately".equals(action)) {
if ("shutdownImmediate".equals(action) || _("Shutdown immediately", ctx).equals(action)) {
ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_HARD));
//ctx.router().shutdown(Router.EXIT_HARD); // never returns
ctx.router().shutdownGracefully(Router.EXIT_HARD); // give the UI time to respond
} else if ("cancelShutdown".equals(action) || "Cancel shutdown".equals(action)) {
} else if ("cancelShutdown".equals(action) || _("Cancel shutdown", ctx).equals(action) ||
_("Cancel restart", ctx).equals(action)) {
ctx.router().cancelGracefulShutdown();
} else if ("restartImmediate".equals(action) || "Restart immediately".equals(action)) {
} else if ("restartImmediate".equals(action) || _("Restart immediately", ctx).equals(action)) {
ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_HARD_RESTART));
//ctx.router().shutdown(Router.EXIT_HARD_RESTART); // never returns
ctx.router().shutdownGracefully(Router.EXIT_HARD_RESTART); // give the UI time to respond
} else if ("restart".equalsIgnoreCase(action)) {
} else if ("restart".equals(action) || _("Restart", ctx).equals(action)) {
ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART));
ctx.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
} else if ("shutdown".equalsIgnoreCase(action)) {
} else if ("shutdown".equals(action) || _("Shutdown", ctx).equals(action)) {
ctx.addShutdownTask(new ConfigServiceHandler.UpdateWrapperManagerTask(Router.EXIT_GRACEFUL));
ctx.router().shutdownGracefully();
}
@ -47,38 +52,40 @@ public class ConfigRestartBean {
boolean shuttingDown = isShuttingDown(ctx);
boolean restarting = isRestarting(ctx);
long timeRemaining = ctx.router().getShutdownTimeRemaining();
if (shuttingDown) {
if (timeRemaining <= 0) {
return "<center><b>Shutdown imminent</b></center>";
} else {
return "<center><b>Shutdown in " + DataHelper.formatDuration(timeRemaining) + "</b></center><br>"
+ buttons(urlBase, systemNonce, "shutdownImmediate,Shutdown immediately,cancelShutdown,Cancel shutdown");
}
StringBuilder buf = new StringBuilder(128);
if ((shuttingDown || restarting) && timeRemaining <= 0) {
buf.append("<center><b>");
if (restarting)
buf.append(_("Restart imminent", ctx));
else
buf.append(_("Shutdown imminent", ctx));
buf.append("</b></center>");
} else if (shuttingDown) {
buf.append("<center><b>");
buf.append(_("Shutdown in {0}", DataHelper.formatDuration(timeRemaining), ctx));
buf.append("</b></center><br>");
buttons(ctx, buf, urlBase, systemNonce, SET1);
} else if (restarting) {
if (timeRemaining <= 0) {
return "<center><b>Restart imminent</b></center>";
} else {
return "<center><b>Restart in " + DataHelper.formatDuration(timeRemaining) + "</b></center><br>"
+ buttons(urlBase, systemNonce, "restartImmediate,Restart immediately,cancelShutdown,Cancel restart");
}
buf.append("<center><b>");
buf.append(_("Restart in {0}", DataHelper.formatDuration(timeRemaining), ctx));
buf.append("</b></center><br>");
buttons(ctx, buf, urlBase, systemNonce, SET2);
} else {
if (System.getProperty("wrapper.version") != null)
return buttons(urlBase, systemNonce, "restart,Restart,shutdown,Shutdown");
buttons(ctx, buf, urlBase, systemNonce, SET3);
else
return buttons(urlBase, systemNonce, "shutdown,Shutdown");
buttons(ctx, buf, urlBase, systemNonce, SET4);
}
return buf.toString();
}
/** @param s value,label,... pairs */
private static String buttons(String url, String nonce, String s) {
StringBuilder buf = new StringBuilder(128);
StringTokenizer tok = new StringTokenizer(s, ",");
private static void buttons(RouterContext ctx, StringBuilder buf, String url, String nonce, String[] s) {
buf.append("<form action=\"").append(url).append("\" method=\"GET\">\n");
buf.append("<input type=\"hidden\" name=\"consoleNonce\" value=\"").append(nonce).append("\" >\n");
while (tok.hasMoreTokens())
buf.append("<button type=\"submit\" name=\"action\" value=\"").append(tok.nextToken()).append("\" >").append(tok.nextToken()).append("</button>\n");
for (int i = 0; i < s.length; i+= 2)
buf.append("<button type=\"submit\" name=\"action\" value=\"").append(s[i]).append("\" >").append(_(s[i+1], ctx)).append("</button>\n");
buf.append("</form>\n");
return buf.toString();
}
private static boolean isShuttingDown(RouterContext ctx) {
@ -96,4 +103,13 @@ public class ConfigRestartBean {
return ctx.router().getShutdownTimeRemaining();
return Long.MAX_VALUE/2; // summaryframe.jsp adds a safety factor so we don't want to overflow...
}
private static String _(String s, RouterContext ctx) {
return Messages.getString(s, ctx);
}
private static String _(String s, Object o, RouterContext ctx) {
return Messages.getString(s, o, ctx);
}
}

View File

@ -50,74 +50,74 @@ public class ConfigServiceHandler extends FormHandler {
protected void processForm() {
if (_action == null) return;
if ("Shutdown gracefully".equals(_action)) {
if (_("Shutdown gracefully").equals(_action)) {
_context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_GRACEFUL));
_context.router().shutdownGracefully();
addFormNotice("Graceful shutdown initiated");
} else if ("Shutdown immediately".equals(_action)) {
addFormNotice(_("Graceful shutdown initiated"));
} else if (_("Shutdown immediately").equals(_action)) {
_context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_HARD));
_context.router().shutdown(Router.EXIT_HARD);
addFormNotice("Shutdown immediately! boom bye bye bad bwoy");
} else if ("Cancel graceful shutdown".equals(_action)) {
addFormNotice(_("Shutdown immediately! boom bye bye bad bwoy"));
} else if (_("Cancel graceful shutdown").equals(_action)) {
_context.router().cancelGracefulShutdown();
addFormNotice("Graceful shutdown cancelled");
} else if ("Graceful restart".equals(_action)) {
addFormNotice(_("Graceful shutdown cancelled"));
} else if (_("Graceful restart").equals(_action)) {
_context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_GRACEFUL_RESTART));
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
addFormNotice("Graceful restart requested");
} else if ("Hard restart".equals(_action)) {
addFormNotice(_("Graceful restart requested"));
} else if (_("Hard restart").equals(_action)) {
_context.addShutdownTask(new UpdateWrapperManagerTask(Router.EXIT_HARD_RESTART));
_context.router().shutdown(Router.EXIT_HARD_RESTART);
addFormNotice("Hard restart requested");
} else if ("Rekey and Restart".equals(_action)) {
addFormNotice("Rekeying after graceful restart");
addFormNotice(_("Hard restart requested"));
} else if (_("Rekey and Restart").equals(_action)) {
addFormNotice(_("Rekeying after graceful restart"));
_context.addShutdownTask(new UpdateWrapperManagerAndRekeyTask(Router.EXIT_GRACEFUL_RESTART));
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL_RESTART);
} else if ("Rekey and Shutdown".equals(_action)) {
addFormNotice("Rekeying after graceful shutdown");
} else if (_("Rekey and Shutdown").equals(_action)) {
addFormNotice(_("Rekeying after graceful shutdown"));
_context.addShutdownTask(new UpdateWrapperManagerAndRekeyTask(Router.EXIT_GRACEFUL));
_context.router().shutdownGracefully(Router.EXIT_GRACEFUL);
} else if ("Run I2P on startup".equals(_action)) {
} else if (_("Run I2P on startup").equals(_action)) {
installService();
} else if ("Don't run I2P on startup".equals(_action)) {
} else if (_("Don't run I2P on startup").equals(_action)) {
uninstallService();
} else if ("Dump threads".equals(_action)) {
} else if (_("Dump threads").equals(_action)) {
try {
WrapperManager.requestThreadDump();
} catch (Throwable t) {
addFormError("Warning: unable to contact the service manager - " + t.getMessage());
}
addFormNotice("Threads dumped to wrapper.log");
} else if ("Show systray icon".equals(_action)) {
} else if (_("Show systray icon").equals(_action)) {
try {
SysTray tray = SysTray.getInstance();
if (tray != null) {
tray.show();
addFormNotice("System tray icon enabled.");
addFormNotice(_("System tray icon enabled."));
} else {
addFormNotice("System tray icon feature not supported on this platform. Sorry!");
addFormNotice(_("System tray icon feature not supported on this platform. Sorry!"));
}
} catch (Throwable t) {
addFormError("Warning: unable to contact the systray manager - " + t.getMessage());
addFormError(_("Warning: unable to contact the systray manager") + " - " + t.getMessage());
}
} else if ("Hide systray icon".equals(_action)) {
} else if (_("Hide systray icon").equals(_action)) {
try {
SysTray tray = SysTray.getInstance();
if (tray != null) {
tray.hide();
addFormNotice("System tray icon disabled.");
addFormNotice(_("System tray icon disabled."));
} else {
addFormNotice("System tray icon feature not supported on this platform. Sorry!");
addFormNotice(_("System tray icon feature not supported on this platform. Sorry!"));
}
} catch (Throwable t) {
addFormError("Warning: unable to contact the systray manager - " + t.getMessage());
addFormError(_("Warning: unable to contact the systray manager") + " - " + t.getMessage());
}
} else if ("View console on startup".equals(_action)) {
} else if (_("View console on startup").equals(_action)) {
browseOnStartup(true);
addFormNotice("Console is to be shown on startup");
} else if ("Do not view console on startup".equals(_action)) {
addFormNotice(_("Console is to be shown on startup"));
} else if (_("Do not view console on startup").equals(_action)) {
browseOnStartup(false);
addFormNotice("Console is not to be shown on startup");
addFormNotice(_("Console is not to be shown on startup"));
} else {
//addFormNotice("Blah blah blah. whatever. I'm not going to " + _action);
}
@ -126,17 +126,17 @@ public class ConfigServiceHandler extends FormHandler {
private void installService() {
try {
Runtime.getRuntime().exec("install_i2p_service_winnt.bat");
addFormNotice("Service installed");
addFormNotice(_("Service installed"));
} catch (IOException ioe) {
addFormError("Warning: unable to install the service - " + ioe.getMessage());
addFormError(_("Warning: unable to install the service") + " - " + ioe.getMessage());
}
}
private void uninstallService() {
try {
Runtime.getRuntime().exec("uninstall_i2p_service_winnt.bat");
addFormNotice("Service removed");
addFormNotice(_("Service removed"));
} catch (IOException ioe) {
addFormError("Warning: unable to remove the service - " + ioe.getMessage());
addFormError(_("Warning: unable to remove the service") + " - " + ioe.getMessage());
}
}

View File

@ -115,10 +115,10 @@ public class ConfigStatsHandler extends FormHandler {
_context.router().setConfigSetting(StatManager.PROP_STAT_FULL, "" + _isFull);
boolean ok = _context.router().saveConfig();
if (ok)
addFormNotice("Stat filter and location updated successfully to: " + stats.toString());
addFormNotice(_("Stat filter and location updated successfully to") + ": " + stats.toString());
else
addFormError("Failed to update the stat filter and location");
addFormNotice("Graph list updated, may take up to 60s to be reflected here and on the <a href=\"graphs.jsp\">Graphs Page</a>");
addFormError(_("Failed to update the stat filter and location"));
addFormNotice(_("Graph list updated, may take up to 60s to be reflected here and on the <a href=\"graphs.jsp\">Graphs Page</a>"));
}
}

View File

@ -32,7 +32,7 @@ public class ConfigTunnelsHandler extends FormHandler {
}
public void setShouldsave(String moo) {
if ( (moo != null) && (moo.equals("Save changes")) )
if ( (moo != null) && (moo.equals(_("Save changes"))) )
_shouldSave = true;
}
@ -132,14 +132,16 @@ public class ConfigTunnelsHandler extends FormHandler {
}
if (updated > 0)
addFormNotice("Updated settings for " + updated + " pools.");
// the count isn't really correct anyway, since we don't check for actual changes
//addFormNotice("Updated settings for " + updated + " pools.");
addFormNotice(_("Updated settings for all pools."));
if (saveRequired) {
boolean saved = _context.router().saveConfig();
if (saved)
addFormNotice("Exploratory tunnel configuration saved successfully.");
addFormNotice(_("Exploratory tunnel configuration saved successfully."));
else
addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs.");
addFormNotice(_("Error saving the configuration (applied but not saved) - please see the error logs."));
}
}
private static final int getInt(Object val) {

View File

@ -8,9 +8,14 @@ import net.i2p.data.Destination;
import net.i2p.router.TunnelPoolSettings;
public class ConfigTunnelsHelper extends HelperBase {
static final String HOP = _x("hop");
static final String TUNNEL = _x("tunnel");
/** dummies for translation */
static final String HOPS = _x("hops");
static final String TUNNELS = _x("tunnels");
public ConfigTunnelsHelper() {}
public String getForm() {
StringBuilder buf = new StringBuilder(1024);
buf.append("<table>\n");
@ -18,7 +23,7 @@ public class ConfigTunnelsHelper extends HelperBase {
TunnelPoolSettings exploratoryOut = _context.tunnelManager().getOutboundSettings();
buf.append("<input type=\"hidden\" name=\"pool.0\" value=\"exploratory\" >");
renderForm(buf, 0, "exploratory", "Exploratory tunnels", exploratoryIn, exploratoryOut);
renderForm(buf, 0, "exploratory", _("Exploratory tunnels"), exploratoryIn, exploratoryOut);
int cur = 1;
Set clients = _context.clientManager().listClients();
@ -38,7 +43,7 @@ public class ConfigTunnelsHelper extends HelperBase {
String prefix = dest.calculateHash().toBase64().substring(0,4);
buf.append("<input type=\"hidden\" name=\"pool.").append(cur).append("\" value=\"");
buf.append(dest.calculateHash().toBase64()).append("\" >");
renderForm(buf, cur, prefix, "Client tunnels for " + name, in, out);
renderForm(buf, cur, prefix, _("Client tunnels for") + " " + _(name), in, out);
cur++;
}
@ -61,95 +66,95 @@ public class ConfigTunnelsHelper extends HelperBase {
in.getLength() + in.getLengthVariance() <= 0 ||
out.getLength() <= 0 ||
out.getLength() + out.getLengthVariance() <= 0)
buf.append("<tr><th colspan=\"3\"><font color=\"red\">ANONYMITY WARNING - Settings include 0-hop tunnels.</font></th></tr>");
buf.append("<tr><th colspan=\"3\"><font color=\"red\">" + _("ANONYMITY WARNING - Settings include 0-hop tunnels.") + "</font></th></tr>");
else if (in.getLength() <= 1 ||
in.getLength() + in.getLengthVariance() <= 1 ||
out.getLength() <= 1 ||
out.getLength() + out.getLengthVariance() <= 1)
buf.append("<tr><th colspan=\"3\"><font color=\"red\">ANONYMITY WARNING - Settings include 1-hop tunnels.</font></th></tr>");
buf.append("<tr><th colspan=\"3\"><font color=\"red\">" + _("ANONYMITY WARNING - Settings include 1-hop tunnels.") + "</font></th></tr>");
if (in.getLength() + Math.abs(in.getLengthVariance()) >= WARN_LENGTH ||
out.getLength() + Math.abs(out.getLengthVariance()) >= WARN_LENGTH)
buf.append("<tr><th colspan=\"3\"><font color=\"red\">PERFORMANCE WARNING - Settings include very long tunnels.</font></th></tr>");
buf.append("<tr><th colspan=\"3\"><font color=\"red\">" + _("PERFORMANCE WARNING - Settings include very long tunnels.") + "</font></th></tr>");
if (in.getQuantity() + in.getBackupQuantity() >= WARN_QUANTITY ||
out.getQuantity() + out.getBackupQuantity() >= WARN_QUANTITY)
buf.append("<tr><th colspan=\"3\"><font color=\"red\">PERFORMANCE WARNING - Settings include high tunnel quantities.</font></th></tr>");
buf.append("<tr><th colspan=\"3\"><font color=\"red\">" + _("PERFORMANCE WARNING - Settings include high tunnel quantities.") + "</font></th></tr>");
buf.append("<tr><th></th><th><img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"Inbound Tunnels\">&nbsp;&nbsp;Inbound</th><th><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound Tunnels\" title=\"Outbound\">&nbsp;&nbsp;Outbound</th></tr>\n");
buf.append("<tr><th></th><th><img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"Inbound Tunnels\">&nbsp;&nbsp;" + _("Inbound") + "</th><th><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound Tunnels\" title=\"Outbound\">&nbsp;&nbsp;" + _("Outbound") + "</th></tr>\n");
// buf.append("<tr><th></th><th>Inbound</th><th>Outbound</th></tr>\n");
// tunnel depth
buf.append("<tr><td align=\"right\" class=\"mediumtags\">Depth:</td>\n");
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Length") + ":</td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".depthInbound\">\n");
int now = in.getLength();
renderOptions(buf, 0, MAX_LENGTH, now, "", "hop");
renderOptions(buf, 0, MAX_LENGTH, now, "", HOP);
if (now > MAX_LENGTH)
renderOptions(buf, now, now, now, "", "hop");
renderOptions(buf, now, now, now, "", HOP);
buf.append("</select></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".depthOutbound\">\n");
now = out.getLength();
renderOptions(buf, 0, MAX_LENGTH, now, "", "hop");
renderOptions(buf, 0, MAX_LENGTH, now, "", HOP);
if (now > MAX_LENGTH)
renderOptions(buf, now, now, now, "", "hop");
renderOptions(buf, now, now, now, "", HOP);
buf.append("</select></td>\n");
buf.append("</tr>\n");
// tunnel depth variance
buf.append("<tr><td align=\"right\" class=\"mediumtags\">Randomization:</td>\n");
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Randomization") + ":</td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".varianceInbound\">\n");
now = in.getLengthVariance();
renderOptions(buf, 0, 0, now, "", "hop");
renderOptions(buf, 1, MAX_VARIANCE, now, "+ 0-", "hop");
renderOptions(buf, MIN_NEG_VARIANCE, -1, now, "+/- 0", "hop");
renderOptions(buf, 0, 0, now, "", HOP);
renderOptions(buf, 1, MAX_VARIANCE, now, "+ 0-", HOP);
renderOptions(buf, MIN_NEG_VARIANCE, -1, now, "+/- 0", HOP);
if (now > MAX_VARIANCE)
renderOptions(buf, now, now, now, "+ 0-", "hop");
renderOptions(buf, now, now, now, "+ 0-", HOP);
else if (now < MIN_NEG_VARIANCE)
renderOptions(buf, now, now, now, "+/- 0", "hop");
renderOptions(buf, now, now, now, "+/- 0", HOP);
buf.append("</select></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".varianceOutbound\">\n");
now = out.getLengthVariance();
renderOptions(buf, 0, 0, now, "", "hop");
renderOptions(buf, 1, MAX_VARIANCE, now, "+ 0-", "hop");
renderOptions(buf, MIN_NEG_VARIANCE, -1, now, "+/- 0", "hop");
renderOptions(buf, 0, 0, now, "", HOP);
renderOptions(buf, 1, MAX_VARIANCE, now, "+ 0-", HOP);
renderOptions(buf, MIN_NEG_VARIANCE, -1, now, "+/- 0", HOP);
if (now > MAX_VARIANCE)
renderOptions(buf, now, now, now, "+ 0-", "hop");
renderOptions(buf, now, now, now, "+ 0-", HOP);
else if (now < MIN_NEG_VARIANCE)
renderOptions(buf, now, now, now, "+/- 0", "hop");
renderOptions(buf, now, now, now, "+/- 0", HOP);
buf.append("</select></td>\n");
// tunnel quantity
buf.append("<tr><td align=\"right\" class=\"mediumtags\">Quantity:</td>\n");
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Quantity") + ":</td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".quantityInbound\">\n");
now = in.getQuantity();
renderOptions(buf, 1, MAX_QUANTITY, now, "", "tunnel");
renderOptions(buf, 1, MAX_QUANTITY, now, "", TUNNEL);
if (now > MAX_QUANTITY)
renderOptions(buf, now, now, now, "", "tunnel");
renderOptions(buf, now, now, now, "", TUNNEL);
buf.append("</select></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".quantityOutbound\">\n");
now = out.getQuantity();
renderOptions(buf, 1, MAX_QUANTITY, now, "", "tunnel");
renderOptions(buf, 1, MAX_QUANTITY, now, "", TUNNEL);
if (now > MAX_QUANTITY)
renderOptions(buf, now, now, now, "", "tunnel");
renderOptions(buf, now, now, now, "", TUNNEL);
buf.append("</select></td>\n");
buf.append("</tr>\n");
// tunnel backup quantity
buf.append("<tr><td align=\"right\" class=\"mediumtags\">Backup quantity:</td>\n");
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Backup quantity") + ":</td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".backupInbound\">\n");
now = in.getBackupQuantity();
renderOptions(buf, 0, MAX_BACKUP_QUANTITY, now, "", "tunnel");
renderOptions(buf, 0, MAX_BACKUP_QUANTITY, now, "", TUNNEL);
if (now > MAX_BACKUP_QUANTITY)
renderOptions(buf, now, now, now, "", "tunnel");
renderOptions(buf, now, now, now, "", TUNNEL);
buf.append("</select></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".backupOutbound\">\n");
now = out.getBackupQuantity();
renderOptions(buf, 0, MAX_BACKUP_QUANTITY, now, "", "tunnel");
renderOptions(buf, 0, MAX_BACKUP_QUANTITY, now, "", TUNNEL);
if (now > MAX_BACKUP_QUANTITY)
renderOptions(buf, now, now, now, "", "tunnel");
renderOptions(buf, now, now, now, "", TUNNEL);
buf.append("</select></td>\n");
buf.append("</tr>\n");
@ -159,7 +164,7 @@ buf.append("<tr><th></th><th><img src=\"/themes/console/images/inbound.png\" alt
// And let's not display them at all unless they have contents, which should be rare.
Properties props = in.getUnknownOptions();
if (props.size() > 0) {
buf.append("<tr><td align=\"right\" class=\"mediumtags\">Inbound options:</td>\n" +
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Inbound options") + ":</td>\n" +
"<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
buf.append(".inboundOptions\" type=\"text\" size=\"32\" disabled=\"true\" " +
"value=\"");
@ -172,7 +177,7 @@ buf.append("<tr><th></th><th><img src=\"/themes/console/images/inbound.png\" alt
}
props = out.getUnknownOptions();
if (props.size() > 0) {
buf.append("<tr><td align=\"right\" class=\"mediumtags\">Outbound options:</td>\n" +
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Outbound options") + ":</td>\n" +
"<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
buf.append(".outboundOptions\" type=\"text\" size=\"32\" disabled=\"true\" " +
"value=\"");
@ -191,9 +196,13 @@ buf.append("<tr><th></th><th><img src=\"/themes/console/images/inbound.png\" alt
buf.append("<option value=\"").append(i).append("\" ");
if (i == now)
buf.append("selected=\"true\" ");
buf.append(">").append(prefix).append(i).append(' ').append(name);
String pname;
// pluralize and then translate
if (i != 1 && i != -1)
buf.append('s');
pname = name + 's';
else
pname = name;
buf.append(">").append(prefix).append(i).append(' ').append(_(pname));
buf.append("</option>\n");
}
}

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