Compare commits

...

1059 Commits

Author SHA1 Message Date
zzz
c90097eca7 0.8.10 2011-10-19 23:43:12 +00:00
a01c11ca1a checking in updated Debian changelog 2011-10-19 19:59:15 +00:00
a57b57f306 restore Serbia & Montenegro 2011-10-19 19:40:11 +00:00
10e412d494 updated before push to tx 2011-10-19 19:36:47 +00:00
6a798fb7b5 Italian update from tx (ty danimoth) 2011-10-19 19:32:59 +00:00
23ad969332 merge of '9c2afc5c3b2920c5284346d3b93a8075fc9d2f37'
and 'cba0dcc238e5631aff5850f49d9cb07ec70e8f65'
2011-10-19 19:22:04 +00:00
zzz
b475e31f70 * I2PTunnel: Fix timeout message on POST (ticket # ) 2011-10-19 19:09:44 +00:00
fda3ef2cfc Update russian translation 2011-10-19 19:03:26 +00:00
zzz
892ef4abe1 reduce RI expiration again 2011-10-19 02:33:45 +00:00
zzz
81093d1342 * StoreJob: Ensure nonzero token
* Tunnels: Connection limit mitigation:
    - Disable tunnel testing
    - Implement closest-to-the-key tunnel selection
    - Use closest-selection in NetDB lookups, stores, and verifies;
      OCMOSJ; and in BuildRequestor
2011-10-18 19:28:47 +00:00
zzz
abd823ab95 dash two 2011-10-17 17:48:43 +00:00
zzz
3bc284b522 hide tunnel lag if testing is disabled 2011-10-17 17:28:57 +00:00
zzz
5f7c971345 return unmodifiable collections 2011-10-17 17:28:37 +00:00
zzz
46a1506c51 log tweak 2011-10-17 17:26:31 +00:00
zzz
0202faf7f9 * SSU: Increase max concurrent outbound attempts;
fix udp.establishRejected stat
2011-10-17 17:25:10 +00:00
zzz
bff518a038 more efficient empty check 2011-10-17 17:23:40 +00:00
zzz
0b293c517f * NetDB: Fix rare NPE from netdb.jsp (ticket #539) 2011-10-17 17:22:23 +00:00
zzz
afd9c2b2c0 * Router: Change all shutdown CRITs to ERRORs; shutdown
the stat manager last to reduce chance of NPEs
    (similar to that in tickets #534,535)
2011-10-17 17:19:57 +00:00
zzz
331da7f4fe javadoc 2011-10-17 17:18:41 +00:00
25a257b6f1 Even though the country no longer exists, re-add Serbia and Montenegro to
countries.txt. zzz: thanks for reminding me that most users will have an old
geoip file.
2011-10-16 16:26:07 +00:00
zzz
82ac0db333 * BuildExecutor: Add tunnel.buildConfigTime stat
* FloodfillMonitorJob: Log tweak (ticket #533)
  * I2CP: Improve error message (ticket #533)
  * JobQueue:
    - Log error when queue is out of order
    - Log tweaks
  * FloodfillPeerSelector: Fix stat NPE (tickets #534,535)
  * RouterThrottle:
    - Fix stat NPE (tickets #534,535)
    - Increase max tunnels and max delay again
  * OutNetMessagePool: Log tweak (ticket #533)
  * Router:
    - Add OOM help (ticket #533)
    - Prevent parallel shutdowns after multiple OOMs (tickets #534,535)
2011-10-15 17:30:24 +00:00
zzz
3dbefa8d01 * SSU: Fix concurrency errors (ticket #536) 2011-10-15 17:21:31 +00:00
zzz
e8712a3a11 * EepGet:
- Add gunzip support (nonproxied only)
    - Clean up progress formatting
  * SSLEepGet:
    - Add gunzip support
    - Increase buffer size
2011-10-15 17:20:30 +00:00
zzz
104594ed59 log cleanup 2011-10-15 17:15:48 +00:00
zzz
a6ce41fac5 * Stats: Add API methods for zero duration, for efficiency 2011-10-15 17:11:40 +00:00
zzz
a97834d2b7 * configupdate.jsp:
- Fix setting to 'never' (ticket #523)
    - Fix always saying trusted keys changed
    - Parameterize tags
2011-10-15 17:09:04 +00:00
485a3ee11a updated translations (fi & sv) from Transifex 2011-10-13 00:35:37 +00:00
b835dbcf4c Add Swedish Debconf translation from Transifex 2011-10-13 00:29:41 +00:00
6a13d22556 Updated English po files to push to Transifex 2011-10-12 23:50:53 +00:00
a296dedebe Add new countries from Maxmind's geoipdb 2011-10-12 23:49:24 +00:00
161e7ca8b2 Add flag for Guernsey from the Open Clip Art Collection, released into the
public domain
2011-10-12 23:47:21 +00:00
zzz
90a70eb245 dont create messages.mo file 2011-10-11 14:04:51 +00:00
zzz
0898b8ee66 fix TCP default 2011-10-11 13:03:46 +00:00
zzz
ab4de7b392 0.8.9 2011-10-10 19:57:56 +00:00
zzz
f39e201067 * Lower max netdb RI expiration again
* Increase default max tunnels
  * Cleanups after review
  * Exorcism (ticket #476)
2011-10-10 19:22:03 +00:00
c884cfe6f6 Debian: Add Polish debconf translation from Transifex 2011-10-08 15:48:01 +00:00
02219f7376 merge of '0cba2bb826dad461c044d43aa12e6e3ad69f6ce1'
and 'ae0b80d9420ce8dcb103095523b98072eada7fa0'
2011-10-08 15:20:33 +00:00
zzz
834054958c Black flags
created by me, public domain
2011-10-08 14:44:56 +00:00
66ba367530 Debian: Disabling build-dep on tor-geoipdb (since our geoipdb is more current) 2011-10-08 10:40:15 +00:00
7652c19699 Abort if bash is not being used 2011-10-07 21:13:39 +00:00
39b741fae1 Add partial Ukrainian debconf translation from Transifex 2011-10-07 19:17:13 +00:00
9493bedb0a update email address and package version in debconf PO files 2011-10-07 19:15:58 +00:00
1647da0abd transifex: enable Ukrainian translation for debconf 2011-10-07 19:13:38 +00:00
921591e61f merge of '126e1ac0cf5610a8cd45831d729d531b8c1d8845'
and 'f9376186d4f489e9726b6750637385b0450f8957'
2011-10-07 18:52:37 +00:00
dec5af96b4 Update russian translations 2011-10-07 17:40:27 +00:00
zzz
39ba081384 * Reseed:
- Restore ovh reseeds, thx mathiasdm
  * Tunnels:
    - For expl. tunnels, fall back to high cap sooner
    - Tweak build rejections for class N
2011-10-07 15:44:06 +00:00
c270e147c1 translation updates from Transifex
* Translation updates from Transifex:
    - I2PSnark: de, es, and pt
    - I2PTunnel: de and es
    - RouterConsole: de and es
    - SusiDNS: de and es
    - SusiMail: de and es
2011-10-07 14:14:36 +00:00
98bfadb763 Update geoip (-28rc)
GeoIP update based on Maxmind GeoLite Country database from 2011-10-07.
2011-10-07 13:26:43 +00:00
bae011da1d Re-adding MessageChannel to I2PSocketFull 2011-10-07 01:26:29 +00:00
6d621d5eb9 Checking in MessageChannel, nothing to see here moving on... 2011-10-07 01:26:10 +00:00
zzz
fa1c18ce2d * Add https reseed thx h2ik 2011-10-07 00:50:45 +00:00
f779993008 Add diftracker.i2p to I2PSnark and hosts.txt 2011-10-06 21:42:38 +00:00
zzz
73c195eb63 -26 2011-10-06 19:05:15 +00:00
zzz
7748147630 fix for final in super 2011-10-06 16:48:48 +00:00
zzz
e193d8964f increase default SSU conn limit 2011-10-06 16:44:33 +00:00
zzz
de71286f3c * Throttle: Increase max message delay 2011-10-06 16:08:14 +00:00
zzz
0f094da348 * RepublishLeaseSetJob:
- Out-of-order JobQueue 3nd try to fix
    - Lower timeouts
2011-10-06 16:07:51 +00:00
zzz
0c3f84c2da * Reseed:
- Update host lists
    - Switch back to https by default
2011-10-06 16:06:52 +00:00
zzz
2332ac2a69 * Transport: Add per-style send processing time stat 2011-10-06 16:06:25 +00:00
zzz
a670100ba3 * UDP: Catch address without key sooner 2011-10-05 22:03:33 +00:00
zzz
979825b07f build fix 2011-10-05 22:01:53 +00:00
648ea64b21 Add debconf to transifex 2011-10-03 21:56:16 +00:00
4fdb9084a6 update due to my changes to jbigi scripts 2011-10-03 01:03:45 +00:00
9fbc7aef25 Taking StandardSocket back since an I2PSocket cannot act like a SocketChannel. 2011-10-01 19:45:10 +00:00
3dd79269bc merge of '7d548bccfc01d30a554dbd176d113a9419be2665'
and 'ccb7faa39e604a125e398cc347f1d5d4da6ac230'
2011-10-01 17:29:48 +00:00
d3999991d0 merge of '4f86a13e5f3de7eb4aae8a1f0f3402e46f262ca2'
and 'ecd077c360b4af5597166def49e62d6a82e57937'
2011-10-01 17:28:57 +00:00
00b9864dbf merge of '1ffee552dec6b7d41faffb34cab1771773dc0bcd'
and '528475be65a5b99629fadd09c3d2f42bbc907914'
2011-10-01 17:22:29 +00:00
c76b098fbb move the info panel to the end of the installation
IMHO, having the information panel ("To start I2P, etc.") displayed at the end
of the installation process makes a lot more sense.

Hopefully others agree...
2011-10-01 17:22:10 +00:00
863fb08fa1 Added rudimentary channel support. 2011-10-01 17:21:53 +00:00
f1ae06ab40 merge of 'c5f06d8a1bcc7468b9b73ccc14f6e8be55b69c64'
and 'cf0a3831f7749e70c42ef5fb231319eebdec2206'
2011-09-30 17:43:28 +00:00
zzz
14c305a494 -24 2011-09-30 17:26:10 +00:00
zzz
4c9023f7cb merge of '2eddbf584c44e72288f74d0f19e716e2a49a847f'
and '45a8f320f0562000d9fb5cb009885b921ab79fdf'
2011-09-30 17:24:14 +00:00
4244b048f8 remove executable attribute 2011-09-30 17:20:09 +00:00
6a15d8c790 update notes about compiling the wrapper in x86_64 Windows 2011-09-30 16:52:12 +00:00
zzz
7afa63ce10 add wrapper version 2011-09-30 16:40:23 +00:00
zzz
66391da1f7 wrapper files for armv7.
Compiled on trimslice
    gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) 
    java version "1.6.0_18"
    OpenJDK Runtime Environment (IcedTea6 1.8.8) (6b18-1.8.8-0ubuntu1~11.04.1)
    OpenJDK Zero VM (build 14.0-b16, mixed mode)
    Wrapper 3.5.12 GPLv2
    All binaries stripped.
2011-09-30 16:08:49 +00:00
a8746e4780 updates to i2prouter based upon changes from 3.5.9 -> 3.5.12 in tanuki's
src/bin/sh.script.in
2011-09-30 16:02:02 +00:00
zzz
af81681beb shorten shitlist time 2011-09-30 16:01:21 +00:00
2926b1734c stripping wrapper binaries 2011-09-30 15:46:07 +00:00
5d43282188 Remove note about the misc/compat6x port; it is no longer required 2011-09-29 22:50:51 +00:00
b96ee4efa2 wrapper upgrade to 3.5.12 / 23-rc
Upgrading our wrapper to 3.5.12 to fix the upstream wrapper's umask bug. All
binaries are from the delta pack except for Win64, FreeBSD, Linux ARM, and OSX
(See history.txt for more info).
2011-09-29 22:35:18 +00:00
6b0fe83989 merge of '435003672b465687f7fa47e037c7f35fb18f84e2'
and 'a61539431697aa07248b384c791007439c38a167'
2011-09-29 21:34:43 +00:00
dev
1c5a9ed042 Added Swedish version of initialNews. 2011-09-29 15:33:39 +00:00
zzz
efaafea78e * Bandwidth refiller: Reinitialize at restart, avoid
issues from clock skews
2011-09-29 13:19:08 +00:00
zzz
273e940fa1 findbugs 2011-09-28 17:05:38 +00:00
zzz
7bac7aaaf3 save space 2011-09-28 17:05:26 +00:00
zzz
9f430bf117 final 2011-09-28 14:11:54 +00:00
zzz
c7f5178b9c alignment tweak 2011-09-28 14:11:16 +00:00
cb3a8b6eac remove accidental cruft leftover from testing 2011-09-27 21:41:08 +00:00
0406b52c9b Disabling exotrack.i2p; it doesn't look like it's coming back... 2011-09-27 20:22:16 +00:00
b62b668d1a Debian: rework j(cpuid|bigi) patches
Patch reworking needed due to my recent edits to the jcpuid/jbigi scripts
2011-09-27 17:53:25 +00:00
40d3aa9d4c Don't call uname -sr, instead call "uname -s". After all, we don't use the kernel
version...
2011-09-27 08:34:53 +00:00
b0ce258925 jcpuid build scripts:
* merge x64 improvements from mbuild.sh into build.sh
* drop mbuild.sh
* add logic to determine the location of JAVA_HOME if not defined.
* update core/c/mbuild to call jcpuid/build.sh
2011-09-27 08:25:32 +00:00
57b30df4eb enable Russian locale for susimail and upload to Transifex 2011-09-26 21:13:27 +00:00
78a8952f55 Russian translation for susimail 2011-09-26 18:21:41 +00:00
c1558b206f merge of '80e2cfeb00b445ea1b638c1c14373c69b98baa9a'
and 'ec02a6ada1c5c1248468085a7158cd0a00a47461'
2011-09-26 17:03:26 +00:00
f9b9877491 Fix "shebang" 2011-09-26 15:33:12 +00:00
zzz
bbd34be212 javadoc 2011-09-24 21:50:10 +00:00
zzz
cc7a8028d1 * HTTPClient: Fix error page not appearing, broken by
StreamForwarder change
2011-09-24 21:49:19 +00:00
zzz
ce5acb490a add some convenience methods 2011-09-24 21:47:51 +00:00
zzz
4822e47156 more mime types not to compress 2011-09-24 21:46:25 +00:00
zzz
a2c867c224 cleanups 2011-09-24 21:45:52 +00:00
zzz
fd1c8c45a8 cleanup 2011-09-24 21:44:51 +00:00
dev
05a92cd8e6 Changed compability flags for Intel Family-6 Model-11 to not be Pentium M compatible.
Beefed up CPUID.Main ot output more info.
Formatting.
2011-09-24 15:44:22 +00:00
1fe8dbb00e source po files pushed to transifex 2011-09-23 20:23:02 +00:00
24fdc4d75e Update Italian, Spanish, and Swedish translations from Transifex 2011-09-23 20:14:24 +00:00
17b19c9724 merge of '45749cb3c6faddac278c7503b3694d2b1dd252e2'
and '6cd04829204378535f6c3836c26dd1b697c2e2e6'
2011-09-22 00:44:51 +00:00
dev
6e236f753d remove a.netdb.i2p2.de 2011-09-21 22:51:16 +00:00
a45c3336a3 merge of '38aa5e61a00e452e95fd63b1a395757595e6ddc1'
and '7683fcc8ce03e5028e6c0b20ab2e4a2acf5c4707'
2011-09-21 18:26:41 +00:00
dev
57523f11c1 added https://netdb.i2p2.de/ as reseed host 2011-09-21 17:55:49 +00:00
597fc5504d rebase patch due to (my) recent changes in core/c/jbigi/mbuild_jbigi.sh 2011-09-21 13:37:44 +00:00
zzz
3df7ef0366 -20 2011-09-20 12:41:49 +00:00
zzz
6e5c9a3a8e merge of '4f9e4125cd99ad55d386c416b659389a6a85a901'
and 'e68b93db0d4031a11910fd17c01edee5d6cd4a96'
2011-09-20 12:40:18 +00:00
zzz
3d91fac2fd * JobQueue, RepublishLeaseSetJob: Out-of-order JobQueue 3rd try to fix 2011-09-20 12:26:18 +00:00
zzz
aec3976896 * I2PTunnel, NTCP: Catch unchecked exceptions from GNU NIO (ticket # 519) 2011-09-20 04:03:01 +00:00
zzz
8a78de2b8c limit max explore queue 2011-09-20 03:28:16 +00:00
zzz
a139d915bd clogged job queue fix 2nd try 2011-09-20 02:54:53 +00:00
450a5e14ab add more platforums for (open|net)bsd 2011-09-20 01:18:16 +00:00
zzz
e6d44a6199 * I2PTunnelHTTPServer: Don't compress small responses or images 2011-09-19 23:50:25 +00:00
zzz
6630c29071 - Close output stream in StreamForwarder to prevent lost data,
existing bug but made worse by larger pipe
2011-09-19 23:37:49 +00:00
8ee6503e54 allow x86_64 or amd64 for the X86_64 systems 2011-09-19 17:42:26 +00:00
zzz
f186076fb0 * i2ptunnel HTTPResponseOutputStream: Use reusable gunzipper
and a larger pipe for efficiency
2011-09-19 14:13:24 +00:00
zzz
49eeed6ac8 * Crypto: Comment out some main() 2011-09-19 13:48:24 +00:00
zzz
35e89b76ca javadoc 2011-09-19 13:47:27 +00:00
zzz
23e262b0b9 * i2psnark: File allocation cleanup to use less heap 2011-09-19 13:46:52 +00:00
zzz
47d2b80aa5 * ClientMessage: Remove unused MessageReceptionInfo
* RouterContext: Remove unused MessageStateMonitor
2011-09-19 13:44:33 +00:00
8aaf9a1c5e Add OPENBSD_PLATFORMS variable (that I missed in the previous commit) 2011-09-19 12:27:03 +00:00
6760d2a5f4 Add (Net|Open)BSD support, clean-ups 2011-09-19 12:23:43 +00:00
d71b71f2b1 Don't prompt to move the wrapper on NetBSD or OpenBSD. 2011-09-19 12:21:38 +00:00
04785e25b9 document installing as a service 2011-09-19 01:27:48 +00:00
2e1692cf09 Add OpenBSD to NBI and CPUID 2011-09-18 20:16:07 +00:00
e92c23c949 typo fix 2011-09-18 17:04:37 +00:00
f2fe5140e1 Add NetBSD support 2011-09-18 16:59:24 +00:00
2261039a76 NetBSD support 2011-09-18 16:56:10 +00:00
2461b9525c Add NetBSD support to NBI and CPUID 2011-09-18 16:25:13 +00:00
7f6c4faeb5 Add "uninstall" as an alternative option for "remove" 2011-09-18 15:37:31 +00:00
a48ed65b36 the arguments to install_i2p_service_winnt.bat aren't required and in some cases cause the installer to hang 2011-09-17 22:17:03 +00:00
03c24ef14e query the status of the service before doing anything 2011-09-17 22:15:45 +00:00
93d3710f51 Don't show "1 file(s) moved" when moving the temporary wrapper.conf in place. Redirect output to nul. 2011-09-17 22:12:40 +00:00
c7385e5e6a *headdesk* I forget to add the wrapper.pid variable. 2011-09-17 20:26:04 +00:00
b1d7df8a8c remove all *.cmd files (they'll never be used in *NIX) 2011-09-17 15:39:54 +00:00
ff601f9ccc change fix_logfile_path's name 2011-09-17 15:38:33 +00:00
2fc0160c40 fix paths to flags (thanks zzz & sorry zzz) 2011-09-17 15:23:05 +00:00
398d264319 rename script to a more appropriate name 2011-09-17 15:02:55 +00:00
7ce82617dc adjust comment 2011-09-17 15:01:13 +00:00
4e52b9c8d7 fix paths to pid files (setting them to explicitly point to %TEMP%) 2011-09-17 14:58:30 +00:00
zzz
dc04414e9a cleanups, logging, javadoc 2011-09-16 14:49:41 +00:00
zzz
a7f8560acf * JobQueue:
- Add warning to setStartAfter() as queue is no longer
      continuously sorted
    - Fix StartExplorerJob not calling requeue()
    - More pumper cleanups
2011-09-16 14:47:40 +00:00
zzz
217cb1f66d * Reseed:
- Add HTTP proxy authorization support
    - Stub out SSL proxy support
    - Disable i2pbote reseed
  * EepGet: Add some new command line options
2011-09-16 14:45:02 +00:00
zzz
1d17981325 * Console: Home page flag spacing 2011-09-16 14:36:02 +00:00
zzz
ba9754ac59 * Router: Fix router changing client-side tunnel options,
causing original tunnel quantity to not be restored
    (ticket #513)
2011-09-16 14:34:52 +00:00
zzz
9a45ba1873 toString() improvement for debugging 2011-09-16 14:34:29 +00:00
zzz
46481fb733 javadoc fix 2011-09-14 13:52:29 +00:00
zzz
87439e19ca * i2psnark:
- Add refresh time option
    - Add public file permissions option (ticket #501)
    - Fix configuration of tunnel parameters (ticket #524)
    - Allow changing I2CP parameters while tunnel is open
    - Remove duplicated options in I2CP options string
    - Don't open tunnel when saving config
2011-09-14 13:06:03 +00:00
zzz
bd06a44706 * Router: Set permissions on router.ping file 2011-09-14 12:59:53 +00:00
zzz
c54dd79b3a * IRC DCC: Fix conn limit options 2011-09-14 12:59:26 +00:00
zzz
e249b22312 * Console: Verify valid host/IP before saving on net config form 2011-09-14 12:58:46 +00:00
667b6b69b6 refreshing patch due to wrapper.config changes 2011-09-14 01:21:15 +00:00
2fa63f8b30 Explicitly setting the umask in wrapper.config 2011-09-14 01:15:10 +00:00
22cb45ac40 Add explicit "install as a service" support for Debian and its derivatives
The upstream script has support for Ubuntu but not Debian. This change allows
the same methods used for Ubuntu to be used for Debian. This *should* work for
any version of Linux that has Debian in its family tree.
2011-09-13 21:36:41 +00:00
8ddc34da45 Refresh patch
Refresh patch to reflect the changes to the i2prouter script
2011-09-13 10:36:15 +00:00
667e4345a0 Fix "bashisms" in tanuki's script 2011-09-13 01:18:58 +00:00
98c44f1bbd Abort by default if I2P is attempted to be started as root; allow setting
ALLOW_ROOT to override.
2011-09-13 01:16:12 +00:00
b0718f6b55 Also set a trap on signal 2 so that the failure message isn't displayed if I2P
is shutdown while running as a console application.
2011-09-13 00:55:37 +00:00
57afc4cd5d Advise to set RUN_AS_USER when installing as a daemon 2011-09-13 00:09:36 +00:00
3a8a8c4256 -17 (i2prouter script update) 2011-09-13 00:06:44 +00:00
3fe50e1d47 fail gracefully when trying to install as a daemon in Arch Linux 2011-09-12 23:03:52 +00:00
c8395df513 update of the i2prouter script based upon Tanuki's 3.5.9 script
With this check-in comes an update of our i2prouter script based upon the
script src/bin/sh.script.in from the 3.5.9 source tarball of the wrapper.

Some of the benefits of this newer version include:
- logic to determine which wrapper binary to use (32bit VS 64bit) and falling
  back to alternate "bitness." This would be most useful for portable packages.
- support for far more platforms and archs than the 3.1.1 based script (such as
  Solaris, risc, os/390, HP-UX, AIX, mips, ia64, etc.)
- support for installing I2P as a daemon in most UNIX-based environments with
  the command "i2prouter install".  The installed service can be removed with
  "i2prouter remove". With testing this option has been confirmed to work in
  OSX, Fedora, Slackware, Debian, Ubuntu, FreeBSD, and SuSE.  It does not work
  in Arch Linux (yet).
2011-09-12 22:53:57 +00:00
2307fed62c switch to tar'ing the osx installer
When zipping with infozip, executable permissions are left intact. When zip is
called with ant, these permissions are lost. When tarring using ant the
permissions seem to be lost too. Switching to calling tar directly ensures that
the executable permissions aren't lost.
2011-09-12 22:52:03 +00:00
fd2c83f052 Change eepget.bat to be parsed when os=windows
osfamily=windows apparently doesn't work in the parseable section (found when
creating a linux only installer).
2011-09-12 17:23:03 +00:00
zzz
0018ac040a run test scripts at release time 2011-09-12 14:51:30 +00:00
zzz
61831b11dc * i2psnark: Fix inaccuracy in the completed bytes display 2011-09-12 14:03:51 +00:00
zzz
540172117f cleanups and comments 2011-09-12 13:11:57 +00:00
zzz
16640722d6 * Build Executor:
- Limit max parallel builds on really slow machines (ticket #519)
    - Slow down build loop when network is apparently disconnected (ticket #519)
2011-09-12 13:10:43 +00:00
zzz
e0c8eb7640 * NetDB: Disable floodfill at shutdown time if enabled 2011-09-12 13:08:50 +00:00
435bc826d3 Add the path to $I2P to eepget.bat
Allow eepget.bat to be called from any location or copied to any location by
adding the full path to the i2p router.
2011-09-12 10:38:30 +00:00
d084d18cfa Update of Windows service installation/removal scripts
These scripts are based on InstallApp-NT.bat.in and UninstallApp-NT.bat.in from
WRAPPERSRC/src/bin of version 3.5.9 of the wrapper.

Tested in XP and Win7.
2011-09-10 15:54:30 +00:00
690f62b3ba Update i2prouter.bat
This is based on WRAPPERSRC/src/bin/StartApp-NT.bat.in from 3.5.9 of the
wrapper. The i2prouter.bat that we ship doesn't work; this one does. Tested in
XP and Win7.
2011-09-10 15:50:49 +00:00
zzz
3aa7f19530 * TunnelDispatcher: Fix bug in -13 preventing participating
tunnels from being expired and causing high CPU usage
2011-09-09 03:56:59 +00:00
zzz
0a83510690 * Blocklist: Include IP in shitlist reason 2011-09-08 14:20:19 +00:00
zzz
f3521228e9 * Blocklist: Include IP in shitlist reason 2011-09-08 14:10:08 +00:00
zzz
ab38e35bcd * NTCP: Hopefully fix race NPE, thx devzero 2011-09-08 14:08:38 +00:00
zzz
b64eff9bbb * Ministreaming: Drop old classes replaced by streaming
years ago.
2011-09-08 13:56:19 +00:00
zzz
4b989eb092 * JobQueue: Change queue from a HashSet to a TreeSet for more efficiency 2011-09-07 01:38:30 +00:00
zzz
8dc1c4fcf4 * Console: Limit max displayed participating tunnels 2011-09-07 01:36:52 +00:00
zzz
8233c4f9e4 cleanups 2011-09-07 01:35:42 +00:00
zzz
e71d2012ca * TunnelDispatcher: Change participant expire List to a Queue for
efficiency and to remove global lock. Also remove separate
    time List for space savings.
2011-09-07 01:34:54 +00:00
b062d3b3dd Adding Jersey and EU flags to the updater 2011-09-06 20:51:14 +00:00
4062782015 Add EU (it's in Maxmind's GeoIP data) 2011-09-06 20:50:35 +00:00
0cc490d286 Add license for Jersey and EU flags 2011-09-06 20:48:03 +00:00
72abe9da13 Add missing country flags
With 0.8.9 we'll be switching to Maxmind's geoip services and they include more
countries than our old source.
2011-09-06 18:20:15 +00:00
zzz
1e5fe1f60b merge of '4f61b159a4d39db3c8eddf2539e9012f5bb375a2'
and '57a19829917d3dc2ad19e95c7b3bafd3673c3903'
2011-09-06 15:32:23 +00:00
zzz
29ef11619a format 2011-09-06 15:29:49 +00:00
zzz
640782ae00 * Console: Move configservice.jsp rendering code from the router to the console 2011-09-06 15:02:28 +00:00
zzz
3882e49231 * JobQueue: Change queue from a List to a Set for efficiency 2011-09-06 13:27:07 +00:00
zzz
b64cb14456 cleanup 2011-09-06 13:24:44 +00:00
zzz
d3950bdcf1 comment out main 2011-09-06 13:24:21 +00:00
zzz
73901f6e2e log fixes 2011-09-06 13:23:39 +00:00
zzz
70d9415ba2 more constructors 2011-09-06 13:23:24 +00:00
zzz
d9b37ac6f0 * I2PTunnel: Save keys to privkey file when enabling
persistent key after tunnel creation (ticket #480)
2011-09-06 13:23:09 +00:00
dc2198d3f6 Debian: Add ability to dump threads to the initscript 2011-09-06 12:39:30 +00:00
zzz
fdc3af97aa * SDSCache: Use weak refs; increase size for pub keys 2011-09-06 12:13:33 +00:00
zzz
5030a86311 field cleanup 2011-09-06 12:12:43 +00:00
zzz
3d5beece87 * Crypto: Rework use of SHA256 for efficiency and
to avoid clogging the Hash cache with one-time hashes,
    and avoiding the global cache lock.
    This also greatly increases Hash cache hit rates.
    Also use SimpleByteCache for temporary byte buffers.
2011-09-06 12:11:55 +00:00
19905e99be removing extraneous trailing space 2011-09-06 01:31:03 +00:00
f79138b356 Fix typo 2011-09-05 03:18:31 +00:00
a40a2df971 merge of '979c520630f94a6647a547535d276e187b753bca'
and 'fb1eccf1532a765266448fe4a13c6f833539a37b'
2011-09-04 23:25:30 +00:00
ebf0128185 merge of '8fb2860840677716bb46ff433868654c31722d3c'
and 'd49c39f3e1dd314595a8608df8761f77520c6550'
2011-09-04 23:10:24 +00:00
zzz
7a135b9fa4 merge of '8fb2860840677716bb46ff433868654c31722d3c'
and '929973e4fe14793240e998315d396a19461655ee'
2011-09-04 23:03:51 +00:00
331fb2781b updated en locale, pushed to transifex 2011-09-04 23:00:45 +00:00
0c319aa184 Add susimail configs for Italian 2011-09-04 22:44:58 +00:00
zzz
2c502c5e27 shorten netdb expiration again 2011-09-04 22:16:04 +00:00
zzz
63958df99b * NetDB: Try again to fix ISJ deadlock, thx devzero 2011-09-04 20:26:47 +00:00
zzz
42fc22eec9 Remove one global lock in OutboundMessageRegistry.
This isn't the cause of the ISJ deadlocks though.
2011-09-04 19:36:08 +00:00
zzz
b39ba06d92 log tweak 2011-09-04 19:34:51 +00:00
baa92b4ed5 Change developer channel
The developers don't hang out in #i2p. They're in #i2p-dev.
2011-09-04 12:51:44 +00:00
070d3ee653 Removing the description of non-existent options (#431) 2011-09-03 19:45:31 +00:00
zzz
6364f142ff * UDP Inbound:
- Hopefully fix race NPE, thx dream
    - Catch some more fragment errors
    - Exception and log tweaks
    - Cleanups and javadocs
2011-09-03 17:44:23 +00:00
zzz
7b974e7e0b * i2psnark: Fix "eject" button in certain browsers (ticket #511)
(fixed on 12/29/10, accidentally reverted in 12/30/10 propagate)
2011-09-03 17:40:24 +00:00
454c7f14a0 Debian: get locale information by sourcing /etc/environment and
/etc/default/locale, if found. This prevents a problem with the encoding being
set to ANSI_X3.4-1968 when I2P is started at boot.
2011-09-02 23:55:32 +00:00
zzz
3d3352438b * NetDB: Hopefully fix ISJ deadlock, thx dream 2011-09-02 17:25:26 +00:00
zzz
b2263efaf0 cache user-agent processing 2011-09-02 17:24:14 +00:00
5f7983ca17 I2PSnark: Fix GUI html tag for adding a torrent, it was missing a space. 2011-09-02 05:02:42 +00:00
zzz
f4e64d9df7 -8 2011-09-02 01:45:05 +00:00
zzz
30702e9b23 sent relay tag cleanup 2011-09-01 23:59:55 +00:00
zzz
1bd71abf66 cache country codes 2011-09-01 23:59:20 +00:00
zzz
d7a4e0357a explore more aggressively if hidden or K 2011-09-01 13:50:17 +00:00
zzz
cdb6313c33 cleanup 2011-09-01 13:50:00 +00:00
zzz
b3711e31ad color by default 2011-09-01 13:25:18 +00:00
zzz
aff250ff13 javadoc 2011-09-01 13:24:47 +00:00
zzz
a69267dc87 UDP cleanups 2011-09-01 13:24:31 +00:00
c9687649a4 The Izpack utility "izpack2exe" doesn't work with 64bit jvms so it's
essentially useless. Perhaps later I'll add a target using launch4j.
2011-08-31 17:13:24 +00:00
9e6f993af5 De-fuglify the service path in Windows
The default service path in Windows is fugly and not very convenient. I2P uses
the correct path, but if you want to access snark or eepsite data, one must go to
%SYSTEMROOT%\config\systemprofile\AppData\Roaming\I2P\ (Vista/7) or
%SYSTEMROOT%\system32\config\systemprofile\Application Data\I2P (XP/2003). If
this wasn't bad enough, in some cases one must take ownership of this path and
grant permission to him- or herself to access the folder.

With this changeset, I'm setting the path to %ALLUSERSPROFILE%\Application
Data\I2P as well as adding a shortcut to the I2P folder in the Start menu.
2011-08-31 17:11:23 +00:00
zzz
b328b47bf4 * OCMOSJ: Remove some global cache locks, other cleanups 2011-08-31 12:52:22 +00:00
zzz
bd7e655788 cleanup 2011-08-31 12:49:33 +00:00
zzz
a928f5ef1f javadoc fixes 2011-08-31 12:48:47 +00:00
zzz
d73eb16aeb * I2CP: Cache b32 lookups client-side
* I2PTunnelHTTPClient: Use existing session for b32 lookups
                         rather than a new SimpleSession
  * Naming: Increase b32 lookup timeout to 15 sec.
2011-08-30 13:41:26 +00:00
zzz
a6728a33da cleanups 2011-08-29 17:53:01 +00:00
zzz
20855c9c44 * Tunnels:
- Increase timeouts on all deferred netdb lookups to 15s; add lookup stats
    - Cleanups, javadocs, log tweaks
2011-08-29 17:51:00 +00:00
zzz
92ffea2237 * NetDB:
- Replace the old parallel lookup method with a true
      Kademlia lookup that iteratively queries additional floodfill
      peers returned in DatabaseSearchReplyMessages. This is a more
      efficient and reliable lookup that will work much better
      when not all floodfill peers are known, and it removes a serious
      limitation to network growth.
    - Limit max number of DSRM entries to look up
    - Cleanups, javadocs, log tweaks
2011-08-29 17:48:08 +00:00
zzz
81240a5240 revert change causing ConcurrentModificationExceptions 2011-08-29 00:50:25 +00:00
zzz
f8df357134 -2 2011-08-28 19:05:06 +00:00
zzz
5b11418209 merge of '35b2e734af9d2aff8fae586fccef3cd66e57e23a'
and 'fb0d6216234531927837fe7b886eb1feab790ecb'
2011-08-28 19:03:01 +00:00
zzz
8b05b16c8a * Log: Fix level stuck at DEBUG when called from constructor 2011-08-28 18:47:13 +00:00
zzz
d4bf3403e1 log tweak 2011-08-28 17:32:58 +00:00
zzz
0c661b373e javadocs 2011-08-28 17:29:42 +00:00
zzz
c8a9d8ef35 cleanups and javadoc 2011-08-28 17:29:14 +00:00
zzz
e768b35848 fix log issue 2011-08-28 17:28:04 +00:00
zzz
5e507c0294 log tweaks 2011-08-28 17:26:34 +00:00
zzz
948de5462f * Stats: Restore pre-0.8.8 API to not create a new Rate if it does not
exist in RateStat.getRate()
2011-08-28 14:31:39 +00:00
035829f33d reworking because of additions to wrapper.config 2011-08-27 23:28:07 +00:00
115f3e1fb0 adding a few new options from the 3.5.9 config file 2011-08-27 23:24:29 +00:00
6a73dffdab Clicking the router console shortcut resulted in a minimized browser window
opening. This change causes the window to not be minimized.
2011-08-27 19:10:41 +00:00
zzz
100f6dac3d simple test script 2011-08-27 15:27:15 +00:00
c671148025 merge of '1f42bc4bfde6612fcb7769fb57d50a224f6bef7e'
and 'ed8df353e5da4216524aa5bc5df052dffe6608dd'
2011-08-27 13:46:52 +00:00
c243f21bff Added reseed.i2p-projekt.de as https:// link 2011-08-27 09:29:20 +00:00
4892764832 changelog update 2011-08-26 23:47:33 +00:00
b9dc7ec12e Set permissions to a SID not to the group Users, fixing a bug that is triggered
on localized versions of Windows.
----
Non-English versions of Windows do not have a Users group; instead they use a
localized group name. As a result, when installing I2P on a non-English Windows
box, the installer will show an error when trying to run the fixperms.bat
script.

Using the SID will work with any localized Windows. SID list @
http://support.microsoft.com/kb/243330/en-us
2011-08-26 23:25:12 +00:00
ab58875b13 The comment is no longer accurate (the file still has UNIX line endings) since
we're using findstr
2011-08-26 15:49:09 +00:00
zzz
c67404e74e remove firewalled and fast message 2011-08-26 13:50:58 +00:00
zzz
5f6efbf6d0 lower some log levels added in last release 2011-08-26 13:45:46 +00:00
f674b78edb Fix ticket #514 (debconf values are overwritten upon installation) 2011-08-25 21:33:06 +00:00
zzz
bb5f3a92b0 history for props, -1 2011-08-25 13:46:45 +00:00
zzz
546b668502 fix NPE after corruption ticket #515 2011-08-24 18:03:56 +00:00
zzz
f6d2ac7fb2 * Blockfile DB: Add reverse lookup table; bump DB rev to 2 2011-08-24 14:25:58 +00:00
zzz
f22865acb1 propagate from branch 'i2p.i2p.zzz.test4' (head a1d80c1c396eaa49c7b46a69397b36fe9717ff2e)
to branch 'i2p.i2p' (head 7d00d6f11ce1172c218ce44b0a8ac28e4addf03d)
2011-08-24 14:24:25 +00:00
zzz
f99f9e41e5 propagate from branch 'i2p.i2p.zzz.test' (head 0f2e109194f1fcc94e8a3f37cbf804446abddeff)
to branch 'i2p.i2p' (head 7bb99f9e0d436cf9923ed17465f15e73c78e7b13)
2011-08-24 14:23:29 +00:00
zzz
3849a96ed2 initial reverse/firewall support 2011-08-24 14:21:44 +00:00
zzz
69701ab506 increase large MTU to 1492 2011-08-24 14:15:09 +00:00
2654ada226 Switch from ant call target 2011-08-23 22:30:33 +00:00
e728532958 copy.jar, delete.jar, etc., aren't used by anything but Windows 2011-08-23 22:29:36 +00:00
2aee4376cb merge of '804bb87106b8e0129d06020ddf5f77ddc242d622'
and 'ebb90f58c9b8363abd9b1f7d8f61c81ca478d811'
2011-08-23 20:18:56 +00:00
zzz
010399d865 0.8.8 2011-08-23 16:07:44 +00:00
73aade4fb3 Proper handling of implied "/" paths 2011-08-23 04:28:05 +00:00
zzz
20c77e1529 fixes after review 2011-08-22 19:09:09 +00:00
zzz
5fd7997661 fix encoding issues 2011-08-21 16:32:15 +00:00
zzz
363a3e57ff cleanups and javadoc fixes 2011-08-21 16:31:46 +00:00
5283b8d127 0.8.8 debian changelog 2011-08-21 10:26:55 +00:00
13545fdd70 ant build now works again on winows 2011-08-21 06:25:32 +00:00
zzz
4c988f0767 spell the language right 2011-08-21 01:11:50 +00:00
dc3f540a64 changing the pastebin on the router console to one that may prove to be more
stable.
2011-08-20 21:13:29 +00:00
zzz
6d064270fc propagate from branch 'i2p.i2p' (head 793ca7c46f5d8b51c5880fc538dea7874e62f63b)
to branch 'i2p.i2p.zzz.test' (head d39f17fe601b6ae514111b07092de820668015d7)
2011-08-20 20:23:27 +00:00
zzz
d20ac3994d propagate from branch 'i2p.i2p' (head 793ca7c46f5d8b51c5880fc538dea7874e62f63b)
to branch 'i2p.i2p.zzz.test4' (head 2ccff1385a7d79f6be7079af73036510667578b7)
2011-08-20 20:23:20 +00:00
c90ac9ee6c I created this script for my own convenience. It isn't used by the Debian
packaging in any way.

Now that I know about ant getBuildNumber, I'll just use that.
2011-08-20 20:03:47 +00:00
67d608a1fb checkpo fixes 2011-08-20 19:54:42 +00:00
zzz
ed7fd9783e checkpo fixes 2011-08-20 19:34:50 +00:00
zzz
994aa72d71 - New Danish and Ukranian translations from transifex
- Update Italian, Chinese, Spanish, Polish, Swedish,
      and Vietnamese translations from transifex
    ** po files contain errors, to be fixed in next checkin
2011-08-20 18:43:34 +00:00
28ed69e575 Add new entries for It, uk, and da. 2011-08-20 17:55:49 +00:00
zzz
b874ff7e87 * Translations: update .tx/config, add Danish and Ukranian 2011-08-20 16:13:15 +00:00
9c0c73358d Add non-x86 target for Linux.
Move the arm and ppc archs for linux from the preppkg target to the non-x86
target.

Make the linux target depend on the x86 and non-x86 targets.
2011-08-20 00:31:12 +00:00
2159862d1a Removing mention of Atalk, which was removed in revision
d07ed83f441d4c357e009e25aa4b55aee518dea3
2011-08-20 00:10:32 +00:00
zzz
c5e74fefe5 * Soft restart:
- Allow NTP to reinitialize clock after the comm system
      in the first minute of uptime
    - Fix i2ptunnels not restarting
    - Increase minimum forward clock shift for soft restart
    - Reduce minimum backward clock shift for soft restart
    - Signal the I2CP client with a different message when restarting
    - I2CP client reconnects when receiving restart message
2011-08-19 15:34:30 +00:00
zzz
26c744ca45 cleanup 2011-08-19 15:30:57 +00:00
zzz
10f3337906 cleanups 2011-08-19 15:30:31 +00:00
zzz
de094433da cleanup 2011-08-19 15:29:37 +00:00
0dee248f8a debian/changelog clarification 2011-08-18 17:37:27 +00:00
674c202e88 Better: Instead of depending on ttf-dejavu, move to recommends and add a note about
TrueType fonts to the description.

Also mention that the jbigi package also includes jcpuid on x86 platforms.
2011-08-18 17:36:00 +00:00
c7b567891c -6 (will wait for 0.8.8 to upload this change to the PPAs) 2011-08-18 17:05:25 +00:00
2f5020e29c Add dependency on ttf-dejavu-(core|extra). Fonts are needed so graphs can be
built with a headless jre. This font will be installed if a non-headless jre is
installed, so this shouldn't be a controversial change.
2011-08-18 17:03:22 +00:00
3f979b159d Bugfix: Don't load the systray in a 64bit JVM in Windows (closes #506) 2011-08-17 21:20:21 +00:00
a9f943154c merge of 'bfd1fde175d4c3de1a107725991aa1b1d611d298'
and 'eb7a90b602d939a3257fb42ab3d826b54ea4da1b'
2011-08-17 19:34:49 +00:00
b3cfe65325 Update russian translation 2011-08-17 19:33:37 +00:00
77e1bf61ca merge of '04def94f04c224d4161392af3cc9147021594fbf'
and '3b0ab08a92774922d853db0303ca405df568a711'
2011-08-17 19:32:32 +00:00
746d440ce0 better NBI logic 2011-08-17 18:55:26 +00:00
zzz
aeccbc975f privkeyfile tweak 2011-08-17 17:46:50 +00:00
zzz
1bf651b88b final 2011-08-17 17:46:05 +00:00
b25a16f171 Now i2ptunnel will generate certificates instead of failing with a permission denied error for trying to write to /i2ptunnel17.privKeys.dat 2011-08-17 03:25:46 +00:00
zzz
421559c26e * Console: Delete corrupt rrd file (ticket #483) 2011-08-16 18:29:57 +00:00
zzz
336e50e94a debug log 2011-08-16 17:46:53 +00:00
zzz
f7c31950b3 UPnP: Fix bug causing failure when the PC has multiple interfaces 2011-08-16 16:20:51 +00:00
zzz
dc02f9cd88 logs page css tweak 2011-08-16 16:14:18 +00:00
095f018fbb Add pastethis.i2p to hosts file. Will add to the router console after the release of 0.8.8. 2011-08-16 12:47:56 +00:00
9c7533bb5d change build target to point to preppkg-unix 2011-08-16 12:45:00 +00:00
a29fd1e90c Add ant targets for custom installers (BSD only, Windows only, etc). 2011-08-16 12:43:37 +00:00
7343e0ff00 fix getBuildNumber target (sometimes the buildNumber would have a leading
space, such as " 19" instead of "19"), using "tr" to strip it.
2011-08-10 23:44:47 +00:00
915755b349 By request: Tighten package dependencies so that the -headless packages are
installed by default if a JRE isn't installed yet. Since the packages
previously depended on "default-jre|java5-runtime|java6-runtime", an
already-installed headless package would have satisfied the dependency.
2011-08-09 14:32:09 +00:00
255ccdcbc1 Allow some variables to be changed by end-users during build by use of a
properties file.
2011-08-07 00:45:14 +00:00
2973b4097d remove osid and postinstall.sh when the installation is complete 2011-08-06 22:38:37 +00:00
9abf7d6aef Don't try to build an EXE on arm systems. 2011-08-06 17:12:19 +00:00
2e6912ed43 Actually copy the script checked-in at bc78eca6ebdc1df6d5d46f197c8e78d320638c15 2011-08-06 12:59:20 +00:00
93d41be5ef As of -3 (debian revision 3) the javadocs are installed to
/usr/share/i2p/docs/javadoc and /usr/share/doc/i2p-doc/api is a symbolic link
to this location. To ensure the link can be created, we check to see if
/usr/share/doc/i2p-doc/api is a folder. If it is, it gets removed.
2011-08-06 01:16:02 +00:00
f428a372cc Correct the path to wrapper.logfile in Windows (see comments in the script for
much more info). Fixes #473
2011-08-06 01:08:18 +00:00
d3861b9917 Remove files from Windows that aren't used in Windows 2011-08-06 00:49:06 +00:00
2fc09679ab fix path to initialNews for target portable-pkg-win32 2011-08-01 18:32:40 +00:00
2679aefb4e Don't set the location of the service's I2P profile to %APPDATA%\I2P. 2011-08-01 09:38:55 +00:00
453b8a962d Debian packaging changelog updates 2011-08-01 01:01:16 +00:00
ecd629f97d Add armv5 (armel) jbigi for Linux 2011-07-31 17:51:07 +00:00
zzz
ee82a6196d * Netdb: Add a job to refresh all the old router infos at startup,
to speed integration
2011-07-31 13:32:44 +00:00
zzz
43afe7b1a8 cleanups 2011-07-31 13:32:07 +00:00
zzz
29ce3c7c8b * Crypto: Implement and then comment out an alternate
AES-256/CBC implementation using the JVM crypto libs,
            and tests, it isn't faster
2011-07-31 13:30:53 +00:00
zzz
1bf86aff0b javadoc 2011-07-31 13:29:22 +00:00
c502c21798 -18 (version bump for linux PPC and OSX jbigis) 2011-07-30 23:31:36 +00:00
3a70a5a627 Add target to build an "osx only" jbigi.jar 2011-07-30 23:29:43 +00:00
3eafe4c765 Add wrapper for Linux on PPC arch 2011-07-30 23:29:08 +00:00
9d3acf98ff Add Linux PPC support 2011-07-30 23:25:14 +00:00
18ee23960c Add jbigi support for Intel Macs
The jnilibs were compiled on Snow Leopard 10.6.8 with Xcode 3.2 (gcc 4.2.1)
2011-07-30 23:18:39 +00:00
3d64df57a1 Fix hang in Linux on armel and ppc architectures by removing unused (per zzz)
lock
2011-07-30 12:31:31 +00:00
zzz
71804173fc add Cryptix license 2011-07-29 21:01:15 +00:00
zzz
dcc1861399 * Netdb Search:
- Follow all DSRM's, not just the last one, by moving the code
      from the match job to the selector
    - Update peer profile after SingleSearchJob
    - Cleanups, javadocs, log tweaks, final
2011-07-29 20:43:52 +00:00
zzz
e7f449472c fast tier size increase 2011-07-29 20:42:47 +00:00
zzz
b37813257a * TunnelPoolManager: Reduce race window for restarting a tunnel pool 2011-07-28 18:26:21 +00:00
zzz
59e1fbd0d1 cleanups 2011-07-28 18:24:11 +00:00
zzz
0d212f6478 dont throw when setting to the same value 2011-07-28 18:23:27 +00:00
zzz
3a1cd51bc7 split up big lock to avoid deadlocks 2011-07-28 18:22:31 +00:00
18db940d59 Add armel wrapper
Compiled on Debian Squeeze within qemu.

GCC version:
Using built-in specs.
Target: arm-linux-gnueabi
Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8'
--with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.4 --enable-shared --enable-multiarch
--enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib
--without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls
--enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc
--disable-sjlj-exceptions --enable-checking=release --build=arm-linux-gnueabi
--host=arm-linux-gnueabi --target=arm-linux-gnueabi
Thread model: posix
gcc version 4.4.5 (Debian 4.4.5-8) 

$ uname -a
Linux debian-armel 2.6.32-5-versatile #1 Wed Jan 12 23:05:11 UTC 2011 armv5tejl GNU/Linux
2011-07-27 00:17:25 +00:00
543e0b0d65 Debian: Minor changes so the jbigi-jni package can be built on non-x86 systems. 2011-07-26 23:28:25 +00:00
zzz
38281ba61f * NativeBigInteger: Move libjbigi-linux-arm.so to libjbigi-linux-armv7.so,
do ARM version detection in NBI.
2011-07-26 23:09:33 +00:00
zzz
a98d521006 * Installer: The previous wrapper files only work on armv7 2011-07-26 21:59:59 +00:00
zzz
b0c2012327 dummy! 2011-07-26 13:38:38 +00:00
zzz
1061e86fad * NetDB:
- Explore even more aggressively at startup
    - Increase SingleSearchJob timeout
    - Increase time at startup for processing DSRM
    - Cleanups, final, javadoc, concurrent
2011-07-26 13:30:54 +00:00
zzz
164b0e5463 * Watchdog: Improve the way it calls for a thread dump 2011-07-26 13:27:40 +00:00
zzz
02bc228d6f log tweak 2011-07-26 13:27:15 +00:00
zzz
a61f113cd1 cleanup for OutNetMessage 2011-07-26 13:27:02 +00:00
zzz
afb6436109 cleanups 2011-07-26 13:26:13 +00:00
zzz
22dd5b8adc add note 2011-07-26 13:26:01 +00:00
fc353ee0bd I added a more sensible error response when a name/b32 won't look up. Also support for "alias" links, as dubiously useful as those may be. (Perhaps allowing absolute paths on eepsites without b32?)" Also it now replaces the aHelperKey with the b64 instead of stupidly leaving the lookup completely unused and pointless. 2011-07-25 23:35:14 +00:00
zzz
734444e183 * UDP:
- Implement destroy message sending
      (receiving was implemented in 0.8.1)
    - More cleanups at shutdown
    - Log tweaks
2011-07-24 18:57:51 +00:00
zzz
89d32e3bef * UDP:
- Revert change in UDPPacket that caused massive corruption
    - Reduce buffer sizes from 2048 to 1536
    - Discard too-large received packets sooner
    - More cleanups
    - Notes on MTU
2011-07-24 15:15:19 +00:00
zzz
ec061eb3e0 more final and cleanups 2011-07-24 12:38:50 +00:00
zzz
702da0a929 * UDP:
- Don't delay in OutboundMessageFragments at the end
      of the loop if we have more to send now, this should
      speed things up
    - More cleanups
2011-07-24 12:16:35 +00:00
zzz
49bba109ac * UDP:
- Complete rewrite of OutboundMessageFragments for
      concurrent and for efficiency to avoid O(n**2) behavior
    - Queue a new send immediately after a packet is acked
    - Cleanups, log tweaks, javadocs, final
2011-07-23 23:16:28 +00:00
zzz
ddec4f88fb propagate from branch 'i2p.i2p' (head 083b9b289063fdcac54734fe782626f5d2be03b1)
to branch 'i2p.i2p.zzz.test4' (head ac597f2218ef1bab8816e1a3d36be95fd7bd79d0)
2011-07-23 16:55:57 +00:00
zzz
3466dc1099 cleanups and comments 2011-07-23 16:55:44 +00:00
dev
bf8f1508cd Changed the equals method to rely on the protected ConcurrentHashMap.equals(). 2011-07-22 15:51:36 +00:00
dev
0235c5ef40 merge of '155618ea1e5d1088da55cc657cc6b6d95e44e862'
and '6060c1530835d871f99ceba7209ed4031c582573'
2011-07-22 15:18:43 +00:00
dev
661325af5a Removed the last Set.entrySet(), sorry zzz. 2011-07-22 14:19:01 +00:00
c716071e9c -14 adds x64 support to the OSX wrapper. With 0.8.7 the wrapper became fat
(i386 & ppc). With this check-in, the wrapper becomes quad-fat (i386, ppc,
x86_64, ppc64).

$ lipo -info libwrapper.jnilib wrapper
Architectures in the fat file: libwrapper.jnilib are: ppc i386 ppc64 x86_64 
Architectures in the fat file: wrapper are: ppc i386 ppc64 x86_64 

$ file libwrapper.jnilib wrapper
libwrapper.jnilib: Mach-O universal binary with 4 architectures
libwrapper.jnilib (for architecture ppc):	Mach-O bundle ppc
libwrapper.jnilib (for architecture i386):	Mach-O bundle i386
libwrapper.jnilib (for architecture ppc64):	Mach-O 64-bit bundle ppc64
libwrapper.jnilib (for architecture x86_64):	Mach-O 64-bit bundle x86_64
wrapper:           Mach-O universal binary with 4 architectures
wrapper (for architecture ppc):	Mach-O executable ppc
wrapper (for architecture i386):	Mach-O executable i386
wrapper (for architecture ppc64):	Mach-O 64-bit executable ppc64
wrapper (for architecture x86_64):	Mach-O 64-bit executable x86_64

Binaries fetched from the tanuki software site and fattened with lipo.
2011-07-22 00:27:28 +00:00
370be48226 Remove extraneous whitespace 2011-07-22 00:23:50 +00:00
zzz
395173613f * Console: Use capability method for counting integrated peers
* Netdb: Speed up collection of all the floodfill peers by using
           PeerManager.getPeersByCapability()
  * PeerManager: Capability cleanups
2011-07-21 15:34:23 +00:00
zzz
046175d866 merge of 'c0d12629a875b5dddde9fd729e05353d54a1bfc7'
and 'd07ed83f441d4c357e009e25aa4b55aee518dea3'
2011-07-21 15:32:44 +00:00
a731c890c2 merge of '6eb926f98c7348ee0979a7252be716e39205bb5e'
and '7a278a1855c16bd22e91f85da2b5167e4a3c3e7e'
2011-07-21 15:30:43 +00:00
zzz
66b19326d5 Dropping apps/atalk demo, which was an awful example as it was apparently written
before streaming existed, so it's trying to do chat and file transfer
with datagrams and no error detection / correction.
2011-07-21 14:53:42 +00:00
dev
23c30a99cb Changed all iterators using entrySet() to values().
Removed debug from main()
Recommented main out.
2011-07-21 13:06:59 +00:00
f4ce899810 merge of '67c0378bd8bbb541f96066910744b28a190bbf44'
and '6826e4301891ae52880ee2533838cc952c7a9118'
2011-07-20 21:17:02 +00:00
zzz
164f6603fd * i2psnark: Don't let connection problem crash the DirMonitor (ticket #495) 2011-07-20 14:47:30 +00:00
88b86333f4 merge of '72d7d8df8b0c2a79750e7f71fcc97cac4728d6b8'
and 'eb9435041f1c76de404d2b6ac10c1219730c9e16'
2011-07-20 14:16:22 +00:00
2669ae0995 add project info to .po 2011-07-20 13:40:43 +00:00
dev
7c4f088b3e Removed unneeded import. 2011-07-20 13:35:21 +00:00
dev
a67adba710 merge of '0274eda1c4130faa95a34ea1d5e468bad761308b'
and '72d7d8df8b0c2a79750e7f71fcc97cac4728d6b8'
2011-07-20 13:33:43 +00:00
dev
73f9b72d63 Sort output of RateStat.getPeriods(). 2011-07-20 13:33:38 +00:00
dev
6e98cf4fe0 merge of '4b9010e6402c729654f8a4766a63e65eeb88df2c'
and 'b768f0483dce793b4654191c2e649de04172087e'
2011-07-20 13:27:49 +00:00
dev
085ca76bcc Added support for adding/removing periods to already existing RateStats. 2011-07-20 13:27:44 +00:00
dev
150270b14f merge of '13af6dbeb49a0ab1855da31595ba3c141e54bc59'
and '6b869c4d924c79a0f7695feaa15a002a061bce06'
2011-07-20 13:23:42 +00:00
dev
9a6888d7f9 Removed double ;;. 2011-07-20 10:16:37 +00:00
6c182ba4bb tweak debian translations 2011-07-20 02:34:41 +00:00
42cffea077 partly update de translation 2011-07-20 01:21:36 +00:00
zzz
3834403c79 propagate from branch 'i2p.i2p' (head e014bb054baa0d8e844e9a97ad6f5b04ed7c0e56)
to branch 'i2p.i2p.zzz.test' (head 1e0af137b9c4c873fea72d661f2ee351a640734f)
2011-07-19 21:18:14 +00:00
zzz
d397eaaa08 - Cleanups, concurrent
- Basic b32 verification
2011-07-19 21:17:52 +00:00
zzz
56d8b72b07 * Tunnel TestJob:
- Don't continue testing after the pool is dead
    - Tweak test intervals
  * TunnelPool: Make more methods package private
2011-07-19 20:54:22 +00:00
zzz
c78719bfe4 cleanup 2011-07-19 20:54:06 +00:00
zzz
91f2206a4f - Set real local address on client side
- Put in some reasonable conn limits
2011-07-18 14:35:55 +00:00
zzz
6d6799b99e * Netdb:
- Add reseed hosts thx matt .at. drollette.com
    - Remove https://a.netdb.i2p2.de/, bad cert for months
    - Remove https://c.netdb.i2p2.de/, no data for months
2011-07-18 14:33:59 +00:00
zzz
3f8df84a4a * Streaming: Improve conn limit log message 2011-07-18 14:29:32 +00:00
zzz
127aebeadc merge of '5985a037ecd49475ed49c120a5ab9d898f058fe6'
and 'adba1e5ca6162b93d450aee8fd7e723bac51abf0'
2011-07-18 14:07:56 +00:00
dbaa659912 Now you can ?i2paddresshelper=<b32>.b32.i2p and the address helper will look up the b32 for you. (Can't/shouldn't add b32s to your addressbook). Tested and it works for me. 2011-07-17 23:54:42 +00:00
zzz
8034dc3ca7 concurrent, final 2011-07-17 19:15:16 +00:00
zzz
0a8abad72e remove code by extending instead of implementing 2011-07-17 18:57:22 +00:00
zzz
a8378d0411 * I2PTunnel: Rename privkey file when deleting tunnel to prevent inadvertent reuse 2011-07-17 16:38:02 +00:00
zzz
7fbb3b12d1 * FileUtil: Add a rename method and a new copy method 2011-07-17 16:33:40 +00:00
zzz
1ced604354 * UDP: Lower max port below 31000 since wrapper uses that 2011-07-17 16:31:21 +00:00
zzz
8a9882c906 generic 2011-07-16 20:44:40 +00:00
zzz
f87e3b52e3 more on resume/accept, untested 2011-07-16 20:22:00 +00:00
zzz
c826f7fb48 cleanups 2011-07-16 20:17:00 +00:00
zzz
59424a899f stub out resume/accept; allow xdcc 2011-07-16 12:46:05 +00:00
zzz
a4ec6a5369 propagate from branch 'i2p.i2p' (head 2072db743073a703da2f4be9707e7edd696c2925)
to branch 'i2p.i2p.zzz.test' (head cc952c7db4822bb6c49c8e6fb6df02a62c6cbe63)
2011-07-15 22:27:31 +00:00
zzz
7ba6f5a755 add gui option 2011-07-15 21:41:38 +00:00
zzz
7fa874f625 - Tracking, expiration, closing of DCC tunnels
- I2PTunnelRunner cleanups
2011-07-15 20:52:18 +00:00
zzz
55bfd6aa2d concurrentify 2011-07-15 20:47:49 +00:00
41021e1abb Fix Arabic CSS routerconsole 2011-07-15 14:04:25 +00:00
zzz
65656b333a eliminate max 2011-07-15 02:12:10 +00:00
zzz
0bf0715adc * Shutdown:
- Cancel our JVM shutdown hook when shutting down
    - Run a spinner task so shutdown always completes
    - exit() instead of halt() so other JVM shutdown hooks run
    - Prevent duplicate wrapper notifier hooks
    - Notify the wrapper twice, once for stopping and once for stopped
2011-07-15 01:13:35 +00:00
zzz
857f0a0448 javadoc links for wrapper 2011-07-15 01:07:35 +00:00
zzz
79ac955b33 * I2PTunnelIRCClient:
- Big refactoring into multiple class files
    - Allow AWAY and CAP messages
    - First cut at DCC support - not for SOCKS (yet)
2011-07-14 20:06:31 +00:00
zzz
252f1047e5 javadocs and final 2011-07-14 18:53:58 +00:00
zzz
9f433b2e6b * Streaming:
- Hook I2CP ports through to I2PSocket
    - Javadocs, init cleanups, final
2011-07-14 18:53:10 +00:00
zzz
dfbf01dad5 * Blocklist:
- Fix delayed lookup of reason from file
    - Tag strings for translation
    - Sort IPs on configpeer.jsp correctly
    - Cleanups
2011-07-13 14:21:42 +00:00
zzz
688634695d javadoc 2011-07-13 14:20:20 +00:00
zzz
3380ecfa28 * SummaryHelper: Fix NPE at startup (ticket #493) 2011-07-13 14:19:34 +00:00
48896568ce added link to translated picture in susidns messages_fr.po 2011-07-13 08:40:10 +00:00
4ad2cf91d7 added link to translated picture in susidns messages_fr.po 2011-07-13 08:31:56 +00:00
15f7981dd2 added link to translated picture in susidns messages_fr.po 2011-07-13 08:21:48 +00:00
30a0ddc3fb upd i2ptunnel & susidns messages_fr.po 2011-07-12 08:07:32 +00:00
526c42b246 merge of '04b92dda3c1b3fa598f3f58762e44e3646c98d80'
and '4b8d5fe248604e47e00c2e674ad30d9678389f80'
2011-07-12 06:43:39 +00:00
zzz
0ca035dc44 merge of '49bba51653177b041a98b902ac624c8feae61698'
and 'f2281f98637dc74181e14a40f3b346436e95be88'
2011-07-10 15:04:50 +00:00
zzz
3455d3f943 * Message Registry: Clear pending messages at restart / shutdown
* OCMOSJ: Clear caches at restart
  * UPnP:
    - Fix device rediscovery and port opening after restart
2011-07-10 15:04:42 +00:00
zzz
42acdc314a * Router Clock: First cut at recognizing and reacting to large system
clock shifts by partially restarting the router. Also improve
    restarts initiated from config.jsp
    Tickets #465, #468, #494
  * UPnP: Wait for a while to ensure port removal at shutdown or restart
2011-07-10 00:00:58 +00:00
zzz
4fd1800944 log tweaks 2011-07-09 23:09:55 +00:00
zzz
dccdb99632 prevent log error at shutdown 2011-07-09 17:26:09 +00:00
zzz
94af227b70 * DH, YK:
- Improve YK speed test
    - Shut down thread faster
    - Refiller keeps going until full
    - Cleanups
2011-07-09 17:11:38 +00:00
zzz
fdd0d6ceb1 remove static log refs 2011-07-09 14:57:41 +00:00
zzz
5402bd0dc2 javadoc 2011-07-09 14:55:34 +00:00
zzz
9d2816f4a7 - Use a different lock for the executor than for shared clients
so shutdown doesn't hang
- Javadocs
2011-07-09 14:30:33 +00:00
2eab528af0 merge of 'f2281f98637dc74181e14a40f3b346436e95be88'
and 'f452317ba7735d99e285e2c580491a100bea305b'
2011-07-09 07:53:12 +00:00
zzz
b41c58341f another NPE from ticket 493 2011-07-08 19:03:38 +00:00
zzz
90b8aa7811 concurrent 2011-07-08 18:31:50 +00:00
zzz
56650ebfb4 more misc. findbugs 2011-07-08 18:05:28 +00:00
zzz
44f4e551b7 more misc findbugs 2011-07-08 17:54:57 +00:00
zzz
9d4cc26890 misc. findbugs fixes 2011-07-08 17:40:43 +00:00
zzz
f173e88787 kill a debug log 2011-07-08 17:05:13 +00:00
zzz
ef40282081 * I2NP: Consolidate common code from TunnelBuildMessage and
TunnelBuildReplyMessage into a common base class
2011-07-08 17:03:19 +00:00
zzz
32d9204e4a * Sha256Standalone:
- Use system SHA-256 MessageDigest instead of Sha256Standalone in PRNG
    - Deprecate DataHelper functions using Sha256Standalone arguments;
      used only by Syndie
    - Note deprecation in javadocs
2011-07-08 13:51:50 +00:00
zzz
dd4906258d javadoc 2011-07-08 13:47:49 +00:00
c4b355124a upd 2011-07-08 13:47:44 +00:00
zzz
15165aa9af * NetDB: Fix NPE at startup (ticket #493) 2011-07-08 13:46:26 +00:00
zzz
c7fcef2096 drop file used only by dropped naming service 2011-07-08 13:44:45 +00:00
zzz
2b4f8ed55c * Blockfile:
- Log error on out-of-order spans
    - Log error on corrupt level and discard
    - Fix SkipSpan non-flush bug causing null levels
    - Add level fixer that repairs nulls and out-of-order levels
    - Fix bug on backwards span construction, not hit in practice
    - Lots of log level changes
2011-07-07 15:19:59 +00:00
681890780c Don't delete debian/copyright during "ant clean".
Instead of deleting debian/copyright with "ant clean", add it to .mtn-ignore.
With the current method, the copyright file doesn't end up in the debian source
package...
2011-07-06 22:27:46 +00:00
zzz
49b39008c5 -5 2011-07-06 12:06:20 +00:00
zzz
98b14158e6 fix error on HTTP Proxy shutdown 2011-07-05 12:47:19 +00:00
zzz
476caf3f59 catch exception on dup entry 2011-07-05 12:46:23 +00:00
zzz
4f3c15eb04 use HostsTxtNamingService if default fails to initialize 2011-07-04 22:07:13 +00:00
zzz
c839799023 increase min floodfills again 2011-07-04 19:16:54 +00:00
zzz
b7ff4fe87a * Netdb exploration:
- Remove floodfills from dont-include list in exploration
      DatabaseLookupMessage, as the dont-include-floodfills flag
      has been supported since release 0.7.9.
      This will make exploration work better, as there is room for
      non-floodfills in the don't-include list now.
    - Reduce min and max exploration intervals
    - Explore aggressively at startup and if known routers is low
    - Explore slowly if known routers is high
2011-07-04 18:48:31 +00:00
zzz
435683c5d1 * Tunnels: Use exploratory tunnels to help maintain a minimum number
of connected peers
2011-07-04 17:43:45 +00:00
zzz
1f3f17c8e6 * PeerManager: Load profiles in separate thread to avoid slowing
down the context initAll()
2011-07-04 16:13:28 +00:00
zzz
d4b28058a7 * EepGet: Add method to add extra headers to request 2011-07-04 14:26:35 +00:00
zzz
43044586d1 * AppContext: Add hasWrapper() method
* Shutdown:
    - Clear more resources in peer manager, netdb, stat manager,
      session key manager, naming service, tunnel dispatcher,
      OCMOSJ (result of testing with jvisualvm)
    - Don't call wrapper on shutdown (starting two threads) if we
      were started with runplain
2011-07-03 13:46:29 +00:00
zzz
6074a02cf5 * I2PThread: Remove logging, too many issues with extra contexts 2011-07-01 11:27:49 +00:00
zzz
57d196edd6 * Router, console, i2psnark: Change three errors to warns (tickets #479, #482, #487) 2011-07-01 11:05:06 +00:00
zzz
bf832a407e * EepGet:
- Fix error output bug
    - Output error data for 504 too
2011-07-01 11:04:09 +00:00
zzz
5ae41521a0 Set Blockfile as default naming service 2011-06-30 12:45:29 +00:00
zzz
d537379798 back to normal-sized updater 2011-06-30 12:43:22 +00:00
zzz
4f5e3401f7 change default news fetch to 36 hours 2011-06-30 12:42:45 +00:00
zzz
81beb63916 propagate from branch 'i2p.i2p.zzz.android' (head cbf2d39e1944b9d601558761d0eedcdebfd2f589)
to branch 'i2p.i2p' (head c2393e50afccfd5682a9086f0eec2a0700cda2c9)
2011-06-30 12:27:00 +00:00
zzz
3a2e9ad5d3 propagate from branch 'i2p.i2p.zzz.test4' (head 50c95d70238ff224e57acfca3d8797990ff3d01d)
to branch 'i2p.i2p' (head 1fa62c230eba5af7849024338fecf51bb2719c4e)
2011-06-30 12:22:12 +00:00
zzz
01b4b227ae small optimization 2011-06-30 12:21:43 +00:00
zzz
f854ac031d change old host name from mixed case to lower case 2011-06-29 21:48:02 +00:00
14e7a8eb12 Debian: If the i2p-doc (javadoc) package is installed, add a javadoc link on
the router console.
2011-06-28 23:19:15 +00:00
1339049886 build_jbigi.sh: make dynamic library build compatible with --as-needed GNU linker flag
See http://www.gentoo.org/proj/en/qa/asneeded.xml for details
2011-06-28 15:57:48 +00:00
zzz
73bd8c8515 * EepGet:
- Add method to get response code
    - Add method to write error data to the output
    - Increase buffer size to 8 KB
2011-06-28 00:03:39 +00:00
e2c7315759 merge of '4016f0b3372bfe07d914506d696a999c20d4c02c'
and '66ef156941e22ca82de6bf0b9ec70dd74c7a130b'
2011-06-27 21:21:32 +00:00
7a9b1297ca Debian: Add -deb1 to router's extra version field 2011-06-27 12:35:49 +00:00
7c255d6cb1 merge of 'a4b347fba401e0a80981d93f36f07b5146665bec'
and 'c25ab2c347bca5e3c4157389ecb6f68c35ce5a6f'
2011-06-27 11:02:58 +00:00
zzz
54aff53afe 0.8.7 2011-06-27 02:25:18 +00:00
zzz
2f10cca40f * Fixes after review:
- Fix Polish po file
    - Install as a service by default on Windows again
    - Change CPUID getters to package private
    - Split new jbigi install messages into two lines
    - Javadocs
2011-06-26 19:07:01 +00:00
ae428394a9 The debian/ directory for 0.8.7-1 (debian revision 1) 2011-06-26 19:04:54 +00:00
zzz
81dd267e29 throw IOE if uncompressed data too big, instead of silently truncating 2011-06-24 17:41:23 +00:00
4ec4013a44 merge of '8a8371472757453d5667080f0ba7a288ff139e5f'
and 'd48e528757ae7b1384eacca6ea802cebfd728841'
2011-06-24 10:55:37 +00:00
46c78ca4a4 debian debconf translation es and de 2011-06-24 10:51:38 +00:00
50bd1c05ac merge of '59d72ad41332fbcf2829c85f6b3e38aaca9ee528'
and 'eff7849dc937d5c853a2fbfb1811eab5f7300296'
2011-06-24 09:14:51 +00:00
36a6667645 update Castillian from transifex plus corrections 2011-06-24 09:11:51 +00:00
225f6a57bc update Castillian 2011-06-24 09:09:47 +00:00
zzz
1fdeba0745 max not min 2011-06-24 01:43:53 +00:00
zzz
f6f748217a allow outbound IRC INVITE 2011-06-23 22:47:52 +00:00
zzz
3f39cea89e propagate from branch 'i2p.i2p' (head 59d72ad41332fbcf2829c85f6b3e38aaca9ee528)
to branch 'i2p.i2p.zzz.android' (head f7e9a993c660229cca575d26a0ba06eea36cea8e)
2011-06-23 17:42:29 +00:00
zzz
bda6d7819c * BlockfileNamingService:
- Support readonly blockfiles
    - Open blockfile readonly if not in router context
    - Log warning if blockfile is locked
2011-06-23 14:35:48 +00:00
5a64a866da -30rc
Add an icon (in OSX parlance, a 'bundle') to the installation folder to start
I2P.  

While there might be a better way to handle this (admittedly, I don't know OSX
that well), it is my belief that this way is less 'hackish' than the various
OSX 'installers' that I've seen floating around.
2011-06-23 10:18:19 +00:00
67fd074f04 * Add note about the versioned lsb-base package dep being dropped.
* Remove the anchor option since we're not using it.
2011-06-23 01:23:06 +00:00
163e748f9c The XInfoPanel was shown twice on OSX because
<os family=unix> covered OSX as well. 

Instead, we'll show the panel for everything *EXCEPT*
Windows.
2011-06-23 01:17:46 +00:00
8f84481d48 Debian: Drop versioned dep on lsb-base so that the I2P package can be installed in
GnewSense.

This change will break nothing since we check for the existence of the lsb
function files in the initscript. With an older version of lsb-base (like the
one that came with Hardy (and GnewSense uses), the output from the initscript
will simply look a little different (but again, nothing will break). Virtually 
everything but GnewSense comes with the desired lsb-base package anyway...
2011-06-22 21:31:31 +00:00
zzz
229f0d1cfd public for android, who isnt starting via Servlet 2011-06-22 13:31:57 +00:00
c1c21e55b4 refresh patch to work with the recent changes to i2prouter 2011-06-21 23:43:04 +00:00
dfd36070eb Setting wrapper.ntservice.interactive=false so that a browser isn't opened at startup in Windows. 2011-06-21 23:42:34 +00:00
43ed1aa320 Make i2prouter fail more gracefully if the wrapper cannot be loaded
(either wrong architecture or i2psvc is just plain missing) and give
a more useful error message.
2011-06-21 22:45:21 +00:00
51282da51e Add russian translation for debconf 2011-06-21 15:00:35 +00:00
aaf50c6e7e routerconsole, susidns: update russian translation 2011-06-21 14:42:08 +00:00
40cd6fd88b merge of '53ab9aa78fdc17db47e5ce39aadcee9cee73cd29'
and 'ec72b34db00b2e5880f02e321a040b625907cc27'
2011-06-20 17:31:36 +00:00
14494e4aae i2psnark, i2ptunnel: update russian translation 2011-06-20 17:30:26 +00:00
d4e8517e9f Add Arabic translation of susimail 2011-06-20 16:29:45 +00:00
526e0cda24 Fixed RTL bug in console: Arabic is displayed with right aligned text using a custom console_ar.css 2011-06-20 16:27:58 +00:00
zzz
e468633408 trim content type 2011-06-20 15:21:03 +00:00
6d59a64eed Adjust the alignment of the langbox's flags 2011-06-19 08:45:29 +00:00
zzz
94e5aafa19 javadoc and more clearing at shutdown 2011-06-18 21:43:59 +00:00
zzz
0fa5fa40e1 * Shutdown:
- More job queue cleanups
    - RouterInfo readin job checks for quick shutdown
    - Note that we should improve profile read job
2011-06-18 19:58:50 +00:00
zzz
4caf48bd86 Fix broken executor initialization 2011-06-18 19:42:08 +00:00
zzz
66aec13ed6 final 2011-06-18 19:41:25 +00:00
zzz
67825a7668 * Shutdown:
- Add final shutdown hook
2011-06-18 17:01:15 +00:00
zzz
facbb8c950 * IRC Server: Send a message back if the tunnel is up but the server is down 2011-06-18 16:33:47 +00:00
zzz
95c88881d9 * Shutdown:
- Stop I2PThread from starting a new App context at shutdown
    - Stop LogWriter from starting a new App context at shutdown
    - Have router kill any leftover App context at startup
2011-06-17 19:51:17 +00:00
zzz
9ad8f35bca * Shutdown:
- Kill the global app context
    - Recognize multi-router case
    - Fix RandomIterator, YKGenerator, DHBuilder, NTCPConnection
      hanging on to old context -
      probably other offenders not yet found
    - Fix DHBuilder thread not stopping
2011-06-17 18:37:02 +00:00
zzz
4f722947e2 bump + rc 2011-06-17 18:26:15 +00:00
5420604ef8 Dropping 0004-configure-updates.patch as it's no longer necessary 2011-06-17 18:15:52 +00:00
47381686b5 Change text to "News updates" instead of "I2P updates" when install location is set to read-only 2011-06-17 18:13:49 +00:00
zzz
df793193aa take3 2011-06-17 03:19:57 +00:00
3bbe3ba707 typo fix 2011-06-17 00:16:54 +00:00
zzz
eeb03766b6 client executor kill take 2 2011-06-17 00:09:05 +00:00
zzz
f8ab2c144e execute the executors 2011-06-16 22:16:21 +00:00
zzz
32793ac12b i2ptunnel shutdown hook 2011-06-16 21:38:08 +00:00
zzz
83ee57adc7 * Shutdown:
- Implement and call shutdown for RouterWatchdog
    - Fix i2psnark DirMonitor not stopping
    - Fix UPnP-Disposer not stopping quickly
    - Implement and call YKGenerator and DHSessionKeyBuilder shutdown
2011-06-16 21:02:56 +00:00
zzz
4cff55daca old TimerTask cleanup 2011-06-16 20:57:13 +00:00
zzz
cb72bb0427 * Shutdown:
- Implement and call shutdown for BandwidthRefiller
    - Implement and register shutdown hook for Timestamper
    - Implement and register shutdown hook for Jetty console server
    - Fix UPnP-SSDPNotifySocket thread not stopping
    - Fix all but one UDP PacketHandler threads not stopping
2011-06-16 19:04:23 +00:00
d2d2b1e25d Prepare debian/ in preparation for 0.8.7 2011-06-16 17:19:10 +00:00
d56f9c7e6e Add another commented example to wrapper.config for those instances in which bindipv6only causes problems 2011-06-16 15:10:53 +00:00
zzz
518fdd8c03 AsyncFortunaRandomSource: Refactor refiller for concurrent and shutdown
Add shutdown hook for FortunaRandomSource
2011-06-16 12:42:25 +00:00
zzz
20ad7a44a7 clear profiles out of memory on shutdown 2011-06-15 15:20:00 +00:00
zzz
c655d23815 * Updates:
- Add the router version to the zip file comment in the updater
    - Add a class to extract the zip file comment
    - Require the sud version header to match the zip file comment
      to prevent spoofing of the version number, since the version
      number in the header is not covered by the sud signature.
2011-06-15 13:30:24 +00:00
ba3f467244 Windows Uninstall the service if I2P is installed, whether the service was enabled by the installer or not. 2011-06-14 22:04:57 +00:00
1a52363218 Attempt to remove the service before trying to install it.
My rationale for this:
1) in case someone is installing I2P on top of an already existing installation
   this will cause I2P to be shutdown
2) no hangs during the installation if i2p is already installed as a service
3) in case the NT service settings are changed in wrapper.config by us, this
   will force the service settings to be updated.
4) versions of I2P < 0.8.7 did not remove the service when uninstalling. If someone
   removed I2P in the past and reinstalls I2P--opting to run as a service--the
   installation process will hang.
2011-06-14 22:00:42 +00:00
336ecda7e6 GOTO lines refer to the non-existent EOF label. Adding the :eof to the end. 2011-06-14 21:45:20 +00:00
zzz
89191f4014 bump 2011-06-14 19:53:13 +00:00
zzz
399a05a5b5 * Router: Delete old libjbigi.so and libjcpuid.so at startup if jbigi.jar is newer.
This will force a reextraction by CPUID and NBI.
2011-06-14 19:37:30 +00:00
zzz
3c88c854bf more cleanup at shutdown 2011-06-14 19:27:46 +00:00
zzz
21b76f1ca1 concurrentify 2011-06-14 19:15:04 +00:00
zzz
d50cf13085 Register shutdown hooks for caches, in the first step of cleaning up
resources on shutdown, which is important in Android as the JVM
isn't going away. More to do.
2011-06-14 19:08:15 +00:00
zzz
620ec536c2 propagate from branch 'i2p.i2p' (head ea4e5cdef1ba51f6eb24828f05dd7ef66d5188ae)
to branch 'i2p.i2p.zzz.android' (head 03199a42adae7400f4627e7391fe3768493fd65f)
2011-06-14 18:48:26 +00:00
zzz
d4ca9ca36d shutdown hook logging 2011-06-14 18:48:09 +00:00
zzz
932f01df0d flag box tweak for two rows 2011-06-14 18:32:56 +00:00
zzz
19fd865e6f new targets for including jbigi in the updater 2011-06-14 18:31:47 +00:00
zzz
09fbc91d32 recognize ktorrent 2011-06-14 18:30:18 +00:00
zzz
38537de758 * NetDB: Increase floodfills and better adjustment based on available memory 2011-06-14 18:29:04 +00:00
zzz
bb8b428598 * jbigi / NBI / wrapper / installer:
jbigi and wrapper files for arm.
    Compiled on trimslice with gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) 
    Log postinstall errors to postinstall.log.
    java version "1.6.0_18"
    OpenJDK Runtime Environment (IcedTea6 1.8.7) (6b18-1.8.7-0ubuntu2.1)
    OpenJDK Zero VM (build 14.0-b16, mixed mode)
    GMP 4.3.2 (half the size of 5.0.2, and no speed difference) LGPLv3
    Wrapper 3.5.9 GPLv2
    All binaries stripped.

    As on the Android emulator, the stock BigInteger.modPow()
    has some serious bug on arm.
    Without the libjbigi checked in here, the JVM crashes almost immediately.
2011-06-14 18:11:43 +00:00
zzz
730965812b final 2011-06-14 18:08:40 +00:00
zzz
c0801297fb merge of 'e1f6b2db3a1f0f1cf4df67f63cf6becd41f534f4'
and 'edb2bfcff621cb4739bdf41520580e3f57bb1b2a'
2011-06-14 18:06:55 +00:00
959f7bf300 Arabic translation update of susidns 2011-06-14 13:43:29 +00:00
a07fb68e14 Windows: Don't install as a service by default.
With this checkin I'm trying to lessen the occurences of ticket #474:

If a user installs I2P on top of an already existing I2P installation with the service
enabled, the installer will hang. The Quit button cannot be clicked. Clicking
the X in the corner seems to roll back the installation.

Also #472: service is not removed when I2P is uninstalled
2011-06-14 12:08:04 +00:00
3c45f57b96 Add gettext to the build-deps for making debian packages 2011-06-13 19:52:07 +00:00
9e5651a9be Add translation notes 2011-06-13 15:14:20 +00:00
41fa06e871 merge of '9d48efc47a48fc445a045f37222713b42a698153'
and 'a9936ae0cadad0b2bb646c9af046b32f3c497188'
2011-06-13 15:13:14 +00:00
51722821e0 Make Finnish, Italian, Polish and Vietnamese translation configurable 2011-06-13 15:04:57 +00:00
a385f0bab2 Fix trailing newline 2011-06-13 15:02:27 +00:00
zzz
6623616c82 - Fail build if gettext fails. Change property at top of build.xml if
you don't have gettext and want the build to continue.
2011-06-13 14:31:41 +00:00
fcf61377ac * Really Clear the execute permissions on *.dll/*freebsd*so/*.jnilib like I meant
to do the first time that I noticed I added these files with those unneccesry
  attributes.
* Set the "manual merge" attribute on these files.
2011-06-13 10:14:23 +00:00
c8ac7bf8fd Remove "Working Directory" from the Uninstaller shortcut in Windows. With the
working directory set to $INSTALL_DIR, C:\Program Files\I2P is not removed in
XP.

...but even with the working directory removed, the the Uninstaller folder is left
within $INSTALL_DIR in Windows 7.
2011-06-12 23:14:02 +00:00
20d0221f5d We will install a copy of the 32 bit version of the wrapper libs when on x64
for use with a 32 bit JRE.

Rationale:
On an x64 system using a 32 bit jvm Without the 32 bit libwrapper, messages
like this will be shown in wrapper.log with the wrapper in MTN & I2P >= 0.8.7:

-----------------------
 Launching a JVM...
 WrapperManager: Initializing...
 WrapperManager: 
 WrapperManager: WARNING - Unable to load the Wrapper's native library 'libwrapper.so'.
 WrapperManager:           The file is located on the path at the following location but
 WrapperManager:           could not be loaded:
 WrapperManager:             $I2P/lib/libwrapper.so
 WrapperManager:           Please verify that the file is both readable and executable by the
 WrapperManager:           current user and that the file has not been corrupted in any way.
 WrapperManager:           One common cause of this problem is running a 32-bit version
 WrapperManager:           of the Wrapper with a 64-bit version of Java, or vica versa.
 WrapperManager:           This is a 32-bit JVM.
 WrapperManager:           Reported cause:
 WrapperManager:             $I2P/lib/libwrapper.so: $I2P/lib/libwrapper.so: 
                           wrong ELF class: ELFCLASS64 (Possible cause: architecture word width mismatch)
 WrapperManager:           System signals will not be handled correctly.
-----------------------

With libwrapper.so removed, one sees the following:

 WrapperManager: WARNING - Unable to load the Wrapper's native library because none of the
 WrapperManager:           following files:
 WrapperManager:             libwrapper-linux-x86-32.so
 WrapperManager:             libwrapper.so
 WrapperManager:           could be located on the following java.library.path:
 WrapperManager:             $I2P
 WrapperManager:             $I2P/lib
 WrapperManager:           Please see the documentation for the wrapper.java.library.path
 WrapperManager:           configuration property.
 WrapperManager:           System signals will not be handled correctly.
-----------------------

The 32 bit lib names, when installed on an x64 system, will match the alternate
names that the wrapper looks for.
2011-06-12 21:42:09 +00:00
ffffd2deb5 Add jcpuid binaries for Intel macs 2011-06-12 16:33:34 +00:00
796d104b83 add support for osx 2011-06-12 00:40:02 +00:00
654aa591c4 add isx86 check for x86_64 too 2011-06-12 00:19:45 +00:00
0a3bbb23e0 Preliminary jbigi support for osx. jcpuid will be coming later. 2011-06-12 00:12:58 +00:00
462d4fb8b2 Add support for OSX to jcpuid's mbuild.sh 2011-06-11 21:22:06 +00:00
eb17390b0a removing \n from the end of three lines to eliminate warnings during build 2011-06-11 17:31:55 +00:00
zzz
550bb1aaae fix the other gzip direction on android too 2011-06-11 17:05:24 +00:00
zzz
20f67ae8e9 Polish i2psnark translation from polacco@mail.i2p.
Fixed single quotes.
Email follows:

...


I attached file "snark-messages_pl.po.gz". I give you permission to use this file in I2PSnark distribution.
If you don't believe me that it is true polish translation, you can check it with some web translator.

Fist I used ordinary text editor to translate. Later I used Poedit <http://www.poedit.net/>.
And I don't know why it gives strange error messages when I save the file.

17:43:29: snark-messages_pl.po:172: a format specification for argument {0} doesn't exist in 'msgstr'
17:43:29: snark-messages_pl.po:177: a format specification for argument {0} doesn't exist in 'msgstr'
17:43:29: msgfmt: found 2 fatal errors

_______
greetz,
polacco
2011-06-11 13:17:09 +00:00
67f351bd50 Susidns in Polish 2011-06-11 12:04:58 +00:00
a87bd3ac50 update country names (some with the help of wikipedia) 2011-06-11 11:31:48 +00:00
e2627f175c Polish (partial) translations 2011-06-11 09:20:32 +00:00
66a2f88da3 Italian (partial) translations 2011-06-11 09:19:24 +00:00
3c9ac0e04d Chinese susimail translation 2011-06-11 09:17:20 +00:00
1bdf97d93f Finnish (partial) translations 2011-06-11 09:16:24 +00:00
08155939c3 Vietnamese (partial) translations 2011-06-11 09:13:28 +00:00
03a022c4fa Add transifex config for new chinese, finnish, italian, polish and vietnamese translations 2011-06-11 09:09:44 +00:00
13b9e42dc4 Update source strings 2011-06-11 08:41:05 +00:00
949d59487c Update with x64 windows info 2011-06-11 00:50:20 +00:00
zzz
3d695dac97 merge of '71a5174ccd130a08639b5c4a72382975747c7b43'
and '9591822ae7297e11b8efacb8456758babb1c6505'
2011-06-10 23:33:21 +00:00
zzz
4fedb3fb5a javadoc thx kytv 2011-06-10 23:30:49 +00:00
25876ffa28 fix formatting 2011-06-10 23:27:38 +00:00
zzz
dba92b0c42 actually use the 64 bit cpu detection 2011-06-10 23:24:54 +00:00
6317418028 New compile using x86_64-w64-mingw32-gcc 2011-06-10 23:05:06 +00:00
59b9694180 Re-add to make sure jbigi-windows-none_64.dll is 'good' 2011-06-10 22:31:26 +00:00
47632a3c4b Windows: Don't copy 32bit wrapper if installed via a 64bit jvm. 2011-06-10 22:28:33 +00:00
zzz
50578b34d0 * Profiles: Skip and delete a corrupt profile read from disk 2011-06-10 22:03:34 +00:00
zzz
c8afe4bcaf * Random: Add config setting prng.bufferSize to override the default 256 KB 2011-06-10 22:01:25 +00:00
zzz
3f5022cbea log tweak 2011-06-10 22:00:35 +00:00
zzz
f7751de1c3 propagate from branch 'i2p.cpuid' (head be49d2042be9311c16ec5cc4b5accd1366b93556)
to branch 'i2p.i2p' (head 0d92feaa69315781a8e98190c6d11b6b91355f8b)
2011-06-10 21:59:42 +00:00
194bd25e7b jbigi for 64bit Windows (jcpuid was checked in earlier).
Tested in Windows 7.
As has been customary, these were linked with gmp-5.0.2.

Built using 
"x86_64-w64-mingw32-gcc (GCC) 4.5.3" on Debian Sid with debug symbols stripped
using x86_64-w64-mingw32-strip.
2011-06-10 21:37:43 +00:00
8677a3e56c jcpuid for x64 Windows 2011-06-10 17:09:04 +00:00
4e99c459c2 all arch wrapper is handled by build.xml 2011-06-10 14:54:41 +00:00
2c0e6a33a4 merge of '14e8f430d97e8e6a9926d59299775ca98d590c8d'
and '2b3daf42c48bc7b83cfa015b1dba87538ee2f8db'
2011-06-10 14:53:59 +00:00
dev
cbaa62dd78 Added debug loggin of .war path. 2011-06-10 14:17:45 +00:00
162c5bca4b New: 64-bit wrapper for Windows.
The Tanuki Software website states "64-bit Windows versions of the Java Service Wrapper
are not currently being made available in the Community Edition." The Makefile
for x86_64 is missing from the upstream tarball as well. 

Well...included in this checkin is a diff against 
$WRAPPER-3.5.9-SRC/src/c/Makefile-windows-x86-32.nmake (see the README in
installer/libs/wrapper/win64.
2011-06-09 20:38:01 +00:00
3d9f68acc6 remove reference to postinstall.bat 2011-06-09 18:06:08 +00:00
7f96e279d7 Since postinstall.bat isn't used any longer:
- removing from /build.xml
- moving recent changes from installer/resources/postinstall.bat to installer/install.xml
- dropping installer/resources/postinstall.bat
2011-06-09 18:04:51 +00:00
zzz
0b4e430c70 * NativeBigI: Add support for atom, core2, corei, nano, pentiumm, geode
* JBigI:
      - Add new libjbigi-linux-xxx.so files built by sponge, now that we have
        CPUID.java support for them (thanks hottuna).
        See http://zzz.i2p/topics/306 for discussion and test results.

        64-bit processors (atom, core2, corei, nano):
        Built with GMP 5.0.2. License is LGPLv3.
        Built by sponge with GCC 4.4.4, downloaded from
        http://sponge.i2p/files/jbigi/gmp-5.0.2/
        For 64-bit processors, both performance testing and
        the GMP changelog http://gmplib.org/gmp5.0.html led us to use 5.0.2
        for both the 32- and 64-bit versions, even though the files are twice as big.
        5.0.x contains specific optimizations for atom and nano.
        All 64-bit libs have _64 appended.

        32-bit processors (pentiumm, geode):
        Built with GMP 4.3.2. License is LGPLv3.
        Built by sponge with GCC 4.4.4, downloaded from
        http://sponge.i2p/files/jbigi/gmp-4.3.2/
        The 4.3.2 files are half the size of those built with GMP 5.0.2, and there was
        little or no performance difference between the two versions for 32 bit processors.
2011-06-09 16:04:06 +00:00
dev
747d1f45a8 Added Geode support. 2011-06-09 15:11:31 +00:00
dev
6cf1591688 Large but simple refactor of CPUInfo interfaces and CPUInfoImpl classes.
Added interface and class for VIA cpus. 
Added support for VIA c5 cpus and some Via nano cpus (a few might be missing).
2011-06-09 15:00:30 +00:00
dev
562cabfbd6 Fixed bad merge, re-added CPU flags hex output. 2011-06-09 13:03:46 +00:00
dev
4033361f10 Added support for PentiumM where applicable. Added P4Compatability for a few processors. 2011-06-09 12:54:48 +00:00
dev
032faaeb73 run identifyCPU() on static for cleaner code. 2011-06-09 09:00:04 +00:00
dev
fd178f6ce5 Removed typos. 2011-06-09 08:45:44 +00:00
dev
28030dd470 Only run identifyCPU() once. 2011-06-09 08:41:51 +00:00
dev
11fb321674 Completed isXXXCompatible support for Bobcat/Atom/Core2/Corei
Added hasX64 for all CPUs.
2011-06-09 07:40:52 +00:00
zzz
3d18255eb1 * LogManager: Use DataHelper methods for loading and storing config 2011-06-08 20:16:48 +00:00
zzz
c5f04ee9c4 - Don't do 'mtn list changed' if not in a workspace or not needed 2011-06-08 20:15:53 +00:00
dev
366ed2b666 Formatting, tabs->spaces 2011-06-08 18:10:13 +00:00
dev
26899e488e Added more fine grained compatability for cpus in CPUID. Not implemented in NativeBigInteger yet. 2011-06-08 18:07:46 +00:00
d57925e848 bump version to -19 to reflect the upgraded wrapper and jcpuid/jbigi binaries for windows and freebsd 2011-06-08 14:07:42 +00:00
zzz
b03f75367d * Build: Add standard manifest to jbigi.jar
* Update wrapper license
2011-06-08 12:44:42 +00:00
dev
2cebe86524 Added support for AMD Bobcat APUs 2011-06-08 08:42:09 +00:00
dev
0a900088ca Formatting 2011-06-08 08:27:01 +00:00
dev
cdb1284e9e Added method for getting extended EBX CPUID flags. 2011-06-08 08:26:37 +00:00
dev
3a5347f88f Remove doCPUID caching, to due to having to much overhead compared to acutally just doing the doCPUID every time. 2011-06-08 08:25:09 +00:00
e18080c4dc clean the jbigi/jcpuid intemediate binaries (core/c/jbigi/{bin,lib} and core/c/jcpuid/lib) 2011-06-08 08:15:23 +00:00
dev
831848e938 Added caching for doCPUID 2011-06-08 08:11:28 +00:00
54ed70ae4a Diable launch-i2psnark (not used) 2011-06-08 08:10:09 +00:00
e3abc25c6b New jbigi/jcpuid compiles for Windows.
Compiled using mingw32 in Windows XP (gcc --version returns v4.5.2).

As was done with the Linux and FreeBSD builds, jbigi was linked with gmp-4.3.2
for the 32bit cpus and 5.0.2 for the 64bit CPUs.

Since there current isn't a free version of the wrapper for x64 Windows, there
aren't any x64 versions of these dlls.
2011-06-08 08:07:53 +00:00
dev
9f9e44bada Improved toString() and formatting. 2011-06-07 20:54:40 +00:00
dev
ff4b6504a1 Formatting 2011-06-07 20:13:00 +00:00
dev
55c6cdcae8 Formatting 2011-06-07 20:06:10 +00:00
00f2750937 Wrapper upgrade, part two. With this checkin I'm adding the new files that
I missed in revision 97672ae2bf487e93c095bb1d142c3df1a2f3d7d7

*Sigh*
2011-06-07 17:40:06 +00:00
dev
9c41bfeaa4 Added support for loading Atom,Core2 and Corei jbigi. 2011-06-07 17:04:15 +00:00
dev
3f43469104 Formatting 2011-06-07 16:35:51 +00:00
dev
89c3f894d7 Added support for most AMD cpus. 2011-06-07 16:27:26 +00:00
dev
33ec7babf9 Added support for a few more intel i3/i5/i7 2011-06-07 15:14:45 +00:00
f5026a9cbf merge of '97672ae2bf487e93c095bb1d142c3df1a2f3d7d7'
and 'a81e35f3ea0e85227f834ec3bd4c40c7c18291f8'
2011-06-07 14:53:50 +00:00
b2e8d3cedf Here is the long awaited upgrade of the wrapper.
The aging v3.1.x of the java wrapper is being replaced in this
checkin with the latest (current) stable release, 3.5.9.

There is now only one copy of wrapper.jar, located in wrapper/all.
The build.xml scripts have been changed to reflect this new path.

All binaries--with the exception of solaris (I don't have 
SPARC hardware)--have been stripped.

FreeBSD x64 is being included in this release.

I have only included the x86 macosx wrapper due to not having a
system to test the x64 code on. On the plus side, the wrapper is 
universal (a FAT powerpc & Intel Mac) binary. No more prompting
to install Rosetta!
2011-06-07 14:53:10 +00:00
dev
6121ccc46f Support additional platforms and processors. 2011-06-07 14:47:29 +00:00
zzz
37ce3305e0 Drop libjbigi-freebsd-viac32.so, dup of libjbigi-freebsd-pentium3.so, case already handled in NBigI. 2011-06-07 14:17:08 +00:00
zzz
f02e44bf91 * Drop andorid/ directory; further development will happen in
an android-only branch.
2011-06-07 14:14:19 +00:00
57fc896e59 Remove leftover debugging "echo" statement 2011-06-07 14:03:11 +00:00
46b4ec4819 Compiled with gcc (GCC) 4.2.1 20070719 [FreeBSD] linked against openjdk6
with PIC and stripped
2011-06-07 11:46:45 +00:00
83ccc0ff0a Change attr execute to false. Files were added with mode 755 in error. 2011-06-07 01:40:49 +00:00
6d70224da4 Add x64 for FreeBSD 2011-06-07 00:57:25 +00:00
7b04c7e210 FreeBSD: Updated jbigi/jcpuid compiles.
Just as was done with Sponge's compiles for Linux, the 32bit libs/cpus were linked with gmp 4.3.2.

The 64bit compiles were linked with gmp 5.0.2. The 32bit compiles for 64bit cpus were linked with 5.0.2 as well.

All .so files were compiled with the default gcc on FreeBSD-8.2-RELEASE
gcc (GCC) 4.2.1 20070719  [FreeBSD]
2011-06-07 00:48:37 +00:00
zzz
95189c8f53 Android:
- Move the classes around
  - Split into Activity and Service
  - Add status bar notification
  - More config changes
2011-06-06 13:47:47 +00:00
zzz
7e84451ac3 Android:
- Import the main_rules file and remove the copied rules
  - Set the version code and name in the apk badging
  - Build target is 8 to allow SD install, MIN-SDK is still 3
  - Fix NPE on new install
  - Remove some debug code from NBigI
2011-06-05 22:38:35 +00:00
15b9615a1c Debian: update path of installed javadocs 2011-06-05 20:02:48 +00:00
4dc9cfb457 Debian: re-work patch to compensate for recent runplain.sh & wrapper.config changes 2011-06-05 20:02:13 +00:00
1250617d6c Make runplain.sh even more shell agnostic 2011-06-05 19:54:21 +00:00
ca5f35aea9 merge of '7f219c63dd48ba4ae26ad87603df4cb41ada2c59'
and 'afa8f9152e731dd11cd6a3649d45caaeb65b1b82'
2011-06-05 15:03:05 +00:00
3dfa982b39 Missing swedish translation and fix of html tags by digitalmannen 2011-06-05 15:02:20 +00:00
zzz
b2a5a94ce0 -18 2011-06-05 14:01:12 +00:00
zzz
d834c8063c merge of '90dce8fafc543f94a2aefe704bf4b3e63b24eab9'
and '9d726cbaf7d1591c47b4dd7e6aed864d2c09e25d'
2011-06-05 13:58:14 +00:00
zzz
d28f4bd24b * JBigI:
- Replace old non-PIC 62-bit linux libs (GMP 4.1.4 built in 2005)
        with PIC libs built with GMP 5.0.2. License is LGPLv3.
        Built by sponge with GCC 4.4.4, downloaded from
        http://sponge.i2p/files/jbigi/gmp-5.0.2/
        For 64-bit processors, both performance testing and
        the GMP changelog led us to use 5.0.2 for both the 32- and 64-bit versions,
        even though the files are twice as big.
        See http://zzz.i2p/topics/306 for discussion and test results.
        libjbigi-linux-athlon64.so was a 64 bit file; by the new naming standard
        supported by NativeBigInteger, it is now a 32-bit file and the
        64-bit one is libjbigi-linux-athlon64_64.so.
        All new 64-bit libs will have _64 appended.
      - Update build docs
2011-06-05 13:52:43 +00:00
zzz
48f4c7286d - Remove libjbigi-windows-athlon64.dll which was a duplicate of libjbigi-windows-athlon.dll;
NBI now tries athlon as a fallback for all 64-bit processors.
2011-06-05 13:31:26 +00:00
zzz
d9f80e9de6 GMP is not in core lib 2011-06-05 12:50:04 +00:00
zzz
d1e42233a8 * DSAEngine: Add code for alternate implementation using Java libs;
disabled by default. Add test code to verify identical results
                 and compare speed.
2011-06-05 12:40:59 +00:00
6110957921 Fix html tags in swedish translation 2011-06-05 11:59:38 +00:00
zzz
d308d7da97 remove unnecessary zeroing code, javadoc 2011-06-05 11:19:32 +00:00
zzz
4d34078678 * Data: Remove duplicate signature verification code
in RouterInfo and LeaseSet
2011-06-05 11:18:35 +00:00
zzz
8d42ebc2f0 * Console: Tag stat descriptions at declaration rather than in Strings.java 2011-06-05 11:16:57 +00:00
zzz
87cad7eaee * JBigI: Replace old non-PIC 32-bit linux libs (GMP 4.1.3 built in 2004)
with PIC libs built with GMP 4.3.2. License is LGPLv3.
             Built by sponge with GCC 4.4.4, downloaded from
             http://sponge.i2p/files/jbigi/gmp-4.3.2/
             The 4.3.2 files are half the size of those built with GMP 5.0.2, and there was
             little or no performance difference between the two versions for 32 bit processors.
             See http://zzz.i2p/topics/306 for discussion and test results.
2011-06-05 11:06:56 +00:00
b1f1c28c5c Swedish translations (thanks 123hund123, hottuna and digitalmannen) 2011-06-05 10:15:05 +00:00
b612e925df merge of 'b87fbef6393383ccfe6d24286dbbf9ffc79fdd29'
and 'c0bbd3c3725889c45887d4cdce900908d8918df8'
2011-06-05 08:51:48 +00:00
af629d2442 minor change to i2psnark l10n es 'n pt 2011-06-05 08:48:58 +00:00
zzz
e232a641a3 android: fix gmp configure args 2011-06-05 02:09:12 +00:00
zzz
35495e4d5a Android:
- Add a version update script
  - Disable NTP
  - Disable external I2CP
2011-06-04 19:31:45 +00:00
zzz
5974160805 * Router:
- Add a lock for reading/writing the router.info file
      - Check our RouterInfo validity after reading and before saving,
        to catch fatal errors sooner
2011-06-04 12:05:48 +00:00
zzz
4e16ef35a2 * KeyGenerator: Restore old return type to not break ABI (thx kytv) 2011-06-04 12:04:18 +00:00
zzz
885d549e84 * NBigI: Recognize Android 2011-06-04 12:03:35 +00:00
zzz
173343e049 Android:
- More efficient build of i2p.jar and crypto.jar
  - More build fixes
  - Merge package configuration resource with configuration file on device if it exists
  - Add launcher icon, resized from installer/resources/eepsite.help/help/lib/itoopie.png
  - Start of a libjbigi build script
  - Increase min API to 3 so we can use JNI
2011-06-04 00:29:02 +00:00
zzz
c3bcb8d020 fix misspelled file causing build dependency problems 2011-06-03 13:20:50 +00:00
zzz
d7de8ae630 Android:
- Fix up build.xml to work with tools version 11
  - Get rid of dot at front of project name
  - README.txt updates
  - logger_config additions
2011-06-03 12:14:54 +00:00
d5f529819f merge of '6ad44c8ad61fa5a65207491cab744ddfa8f0f3ca'
and 'db7c4479731f94687d64bea76eafeb4c62e14f1a'
2011-06-03 01:31:31 +00:00
d2093444a6 update i2psnark pt 2011-06-02 21:34:50 +00:00
3f15c4324b update i2psnark one string in es and de 2011-06-02 20:32:49 +00:00
zzz
219d7fd8c3 fix ElGamalTest compile; fix jbigi.jar path to speed up the test 2011-06-02 20:29:15 +00:00
c5c6a9fa17 update routerconsole Deutsch 2011-06-02 20:23:36 +00:00
78779fe92f update Castillian 2011-06-02 19:36:53 +00:00
b37a64905b fix/merge 2011-06-02 19:07:38 +00:00
675ac79443 merge of '65af54c284a3e8def1740b26114d3ed42ccae172'
and 'd805aad2dab23264b9c386c8ffabea464fece871'
2011-06-02 19:02:29 +00:00
14ea9c2928 fix/merge 2011-06-02 19:02:12 +00:00
ec6084cd37 merge of '468d5271753b5b44fff6890ecd33d03b684d8e18'
and 'cd4b79fe5aae3f17a3def305c7a3494a8db5dc74'
2011-06-02 18:57:06 +00:00
b65cbb0f78 Remove txt file in BOB.jar as per zzz's request. 2011-06-02 18:53:45 +00:00
zzz
fe15db51d8 - Logging tweaks inspired by Android
- Disable reusing Deflater on Android
2011-06-02 18:29:06 +00:00
zzz
761ad38bcc * HMAC:
- Javadocs and cleanups
      - Use SimpleByteCache
      - Comments and speculation
2011-06-02 13:37:35 +00:00
zzz
2a5ed938bb update generateKeyPair() return type to make it easier 2011-06-02 13:34:26 +00:00
zzz
c5c4e3c7ce * ElGamalAESEngine: Fixups required after SessionKey enforcement
* SessionKey: Enforce data size and prevent reuse like the other SimpleDataStructures
2011-06-02 13:33:03 +00:00
zzz
94af6550fa HMAC256 is used by Syndie 2011-06-02 13:30:33 +00:00
zzz
c767644c8f typo 2011-06-02 13:29:27 +00:00
zzz
a3ee593d0b give up on a reseed host after 90% errors 2011-06-02 13:27:03 +00:00
zzz
733d6db56e one more illegal character 2011-06-02 13:25:23 +00:00
zzz
6d938a12f6 android build fixes 2011-06-02 13:24:47 +00:00
8a56531c90 Don't prefer IPv4 but add the option commented out to wrapper.config. Make the option configurable in runplain.sh 2011-06-01 14:42:18 +00:00
zzz
43332bb6d0 * Crypto:
- Use java.security.MessageDigest instead of bundled GNU SHA-256 code
        if available, which it should always be.
        5 to 20% faster on Oracle JVM; 40 to 60% on Harmony;
        5 to 15% on JamVM; 20x (!) on GIJ.
      - Use java.security.MessageDigest instead of bundled Bitzi SHA-1 code
        if available on non-Oracle JVMs, which it should always be.
        Not faster on Oracle JVM; 30 to 60% faster on Harmony;
        15 to 20% on JamVM; 10-15x (!) on GIJ.
2011-06-01 11:44:10 +00:00
5990dd5879 add description for debian-clean target 2011-06-01 10:24:07 +00:00
030a95cdd1 reference debianhowto 2011-06-01 09:54:32 +00:00
18d3536ffe ConfigClients stopClient stubbed out. 2011-06-01 03:59:12 +00:00
3b80f53b8e There is more than one way to peel a pineapple... 2011-06-01 02:49:14 +00:00
5912c60692 Remove the one little html file that ends up in BOB.jar. The file is NOT a javadoc file, it is a package file. Still, it is zapped. 2011-06-01 02:32:00 +00:00
f8dc8a298e Debian: refactor patch 2011-06-01 00:11:03 +00:00
a3dd538afb typo fix 2011-06-01 00:09:53 +00:00
a90b8aa03a Prefer IPv4 connections
In some distributions (such as Debian, for example) net.ipv6.bindv6only=1 is
set by default. In some configurations, networking in java applications will be
broken. Someone recently came into #i2p experiencing this very problem.

This change closes #464.
2011-06-01 00:04:23 +00:00
313ee79bae hide syndie from "all" target and disable syndie target 2011-05-31 23:32:27 +00:00
97f97448d5 Clean up debian options in build.xml 2011-05-31 23:29:06 +00:00
zzz
3677cadcca * jbigi: Add support for solaris 2011-05-31 20:21:51 +00:00
455b5529b4 jbigi: Add support for SunOS/Nexenta/Solaris to the build*.sh scripts 2011-05-31 19:37:29 +00:00
60204fef24 Debian: initscript: Don't spew warnings when chown'ing files that don't yet exist 2011-05-31 18:50:54 +00:00
45064ec37e libjcpuid for Solaris x86
Compiled using
gcc (GCC) 4.2.3 (Ubuntu 4.2.3-2nexenta7) on Nexenta 3.0.1
2011-05-31 18:20:32 +00:00
zzz
4ecacc7607 * HTTP Proxy: Don't send redirect for POST (thx kytv) 2011-05-31 15:57:39 +00:00
43ba27126c Debian: Refactor jcpuid & jbigi patches to deal with SunOS support 2011-05-31 11:32:07 +00:00
527c9ba5dd Add support to jbigi/jcpuid for Solaris/SunOS 2011-05-31 11:30:10 +00:00
zzz
d4bf2523a6 * I2CP:
- Append I2CP Version information to the Get/Set Date Messages,
        so that both the router and client are aware of the other side's version,
        and future protocol changes will be easier to implement.
        Previously, router version information was not available to the client,
        so when router and client were in different JVMs,
        old clients would work with new routers
        but new clients would not work with old routers.
        After this change, we can design future changes so that new clients
        will work with old routers.
        This is an enhancement to the old protocol version byte sent by the client,
        which we have never changed and probably never will.
      - Prevent a client from setting the router's clock
      - Javadocs
2011-05-30 16:31:09 +00:00
zzz
acb4bac5e6 * netDb: Don't refetch expiring router infos if we have enough 2011-05-30 16:29:33 +00:00
zzz
cbef38ac11 * i2psnark: Restrict swarm size for small torrents 2011-05-30 16:25:24 +00:00
f9ffab62f4 Debian: Refactor jcpuid patch
Changes made to patch b/c of  kFreeBSD changes to build.sh I recently checked
in.
2011-05-29 15:12:46 +00:00
656292e1b1 Debian: Since jetty-i2psnark.xml has been disabled, there are no xml files dumped to pkg-temp. 2011-05-28 21:36:17 +00:00
ed8a065da9 Debian: Rework patch to work with the updated runplain.sh 2011-05-28 20:21:45 +00:00
9834a36787 merge of '5b0e335af7a9ce35cb7e40cd550b7e65af923218'
and 'd25f86bdd190afae59745e22e4fd0c2d8911a8ac'
2011-05-28 20:17:09 +00:00
33b9a5c2ce Make runplain shell agnostic
Braces were put around variable names so that router will run in kFreeBSD.
runplain.sh should now be shell agnostic (it runs in dash. it even runs in
*posh*, a ridiculously picky shell).
2011-05-28 20:14:36 +00:00
zzz
1eb58a84df * i2psnark: Fix bug preventing Robert from connecting to snark (thx sponge) 2011-05-28 20:11:52 +00:00
c9c35a3e5a jcpuid: minor edits so that compilation will work with Debian kFreeBSD 2011-05-28 17:26:24 +00:00
e0dd52a4dc build.xml: Don't copy jetty-i2psnark.xml to pkg-temp 2011-05-28 12:52:23 +00:00
zzz
393d813d05 Don't re-append the query string to the redirect URL,
which caused eepget to repeatedly retry the new redirect
of an i2paddresshelper query by the HTTP proxy.

This was clearly non-compliant (the Location: header requires
an absolute URI including any query string).

This was part of the original redirect handling added by
jrandom to eepget back when it was in syndie;
appending that changelog just in case this hackery was
required by Freenet USKs, which I doubt.

Also, reset the redirect counter when retrying.

==============

	Revision: 62a8cac8565958d111d0a47a443c964918d2e3ef
	Parent:   277fe109ea4416f7d8a6dba6e09cd4f605a8ce1a
	Author:   jrandom@i2p.net
	Date:     10/22/2006 15:06:30
	Branch:   i2p.syndie

	Changelog: 
	    ...
	    - add support for HTTP 301 redirects to EepGet (so freenet USKs work as
	      intended)
2011-05-27 21:41:49 +00:00
0000e4f28d Debian: Ship custom router.config to disable updates via the I2P router. Updates, to keep with Debian policy, must be done via the package manager. 2011-05-27 17:43:05 +00:00
zzz
e3a3a99317 add cpuid 2011-05-27 16:18:38 +00:00
zzz
6a9f73bd61 quick jbigi test script 2011-05-27 16:12:10 +00:00
zzz
2c3be29016 * JBigI:
- Refactor to handle 64 bit libs and a list of fallback libs
      - Logging tweaks
      - Only check for one file name in library path
2011-05-27 15:04:40 +00:00
zzz
8eb10872b8 * CPUID:
- Recognize amd64 as x86
      - Only check for one file name in library path
      - Log tweaks
2011-05-27 15:02:03 +00:00
zzz
d5fd682985 * Console: Fix router.updateThroughProxy being set to false after saving
change on /configupdate when install dir is read-only.
               (ticket #466)
2011-05-27 14:58:57 +00:00
zzz
8f861f7ba2 javadoc 2011-05-27 14:57:36 +00:00
efe53c831d Debian: Since browser launch is disabled within the I2P codebase for the i2psvc user, removing patch to disable it 2011-05-27 13:35:36 +00:00
0dba0a1d6f typo fix 2011-05-27 09:45:42 +00:00
89c01696cc Debian: Remove cruft that remained in debian/rules from the times in which cpuid couldn't be build for i386. 2011-05-27 09:35:17 +00:00
164f060a40 Debian: Creating a new fourth package by splitting the i2p package in two
This commit splits the i2p package into a second package, i2p-router.
   * The new 'i2p-router' package does not depend on the java-wrapper nor jbigi.
     Jbigi is recommended. This package can be installed on the ports or 
     distributions that the java-wrapper is not available for.
   * The new 'i2p' package depends on i2p-router, libjbigi-jni, and the java-wrapper. 
     This package will add the i2psvc system user and the initscript. Existing
     users of the i2p package will have the i2p-router package pulled in
     automatically and for them there will be no usability changes.

 Executive summary: No functionality changes will take place for either those
		    that installed the i2p package in the past or those that
		    install the newly split i2p package. For them, "The Song
                    Remains the Same."
2011-05-27 09:33:20 +00:00
e347ee5880 Debian: debian/README.Debian updates to reflect packaging changes 2011-05-26 21:56:42 +00:00
a4ea70b33b Debian: Move scripts/ to doc/i2p/examples 2011-05-26 21:40:31 +00:00
4433a3db06 Debian: Install runplain.sh as /usr/bin/i2prouter-nowrapper 2011-05-26 21:38:50 +00:00
e019d3b8d7 Debian: create symlinks in doc/licenses that point to existing licenses in /usr/share/common-licenses 2011-05-26 21:33:05 +00:00
1f497e171a Debian: Add certificates directory to $I2P 2011-05-26 19:12:32 +00:00
cd8c954513 Debian: Drop junit from Build-Depends-Indep 2011-05-26 18:53:22 +00:00
d08d5ffd64 Debian: add debian/copyright to ant clean target 2011-05-26 18:51:36 +00:00
8744eab46d Debian: drop dynamically created copyright file 2011-05-26 18:46:41 +00:00
5d7e936aed Remove legacy standalone i2psnark from package 2011-05-26 15:49:43 +00:00
e786da2605 Remove information from debian/README.Debian that is no longer applicable 2011-05-26 14:45:10 +00:00
b6fab829cc Debian packaging fixes 2011-05-25 23:09:58 +00:00
zzz
150cb30339 minor NBI tweaks and comments 2011-05-25 22:13:18 +00:00
zzz
724d8de9ae call the 64 bit cpuid, even if we dont use it yet 2011-05-25 21:35:21 +00:00
zzz
ddcd8cbb10 prep for new 32 bit cpus 2011-05-25 21:23:40 +00:00
zzz
f5f4f14b7e Drop libjbigi-linux-k63.so and libjbigi-freebsd-k63.so that were identical
to k62 versions; add mapping in NativeBigInteger.
2011-05-25 21:14:16 +00:00
zzz
6616ccd3b4 cleanup in prep for more changes 2011-05-25 21:05:20 +00:00
075f89f43c Update jetty version number--we use version 5.1.15. 2011-05-25 18:11:15 +00:00
9a836ed072 merge of '0ab9435836f60e748b89344771eea555219e6262'
and '13180c845a0d2cce619be3b9b139295f2ff49ece'
2011-05-25 17:09:29 +00:00
zzz
552608744d * CPUID: If the 64 bit extract worked but the load failed, try 32 bit 2011-05-25 16:54:25 +00:00
2accbdcf05 Operation close #354 part one of ??: Make the router console's help pages valid html. We *LOVE* valid HTML. 2011-05-25 16:52:52 +00:00
ab17bd3150 Built using gcc (Debian 4.4.5-8) 4.4.5 in Debian Squeeze within clean chroot jails.
-fPIC and stripped.
2011-05-25 16:00:11 +00:00
zzz
d201a29d03 * HTTP Proxy: Address helper refactoring, address book add form 2011-05-25 13:52:18 +00:00
zzz
c4bbcc4617 * CPUID: Load 64-bit libcpuid if available 2011-05-25 13:48:45 +00:00
zzz
82a0ac16f1 increase min floodfills again 2011-05-25 13:36:17 +00:00
zzz
27b48034c5 b32 cleanups 2011-05-25 13:34:32 +00:00
641e71c141 close tags in eepsite help files 2011-05-24 23:16:15 +00:00
4fd8da8041 Fix errors that tests/scripts/checkxml.sh found 2011-05-24 22:33:28 +00:00
zzz
68dccdfe2f try to fix RrdGraph GIF exception 2011-05-23 23:24:54 +00:00
zzz
592361b1a4 * Console:
- Disable zh translation in graphs on windows due to font issues
      - Fix NPE at startup
      - Graph tweaks
2011-05-23 19:22:33 +00:00
zzz
6e4df8830a - Force news refetch after URL change 2011-05-23 19:19:07 +00:00
zzz
7ab95d0144 javadoc 2011-05-23 19:16:33 +00:00
4ea5622842 mbuild.sh fixups : add new jcpuid/mbuild.sh, edit jbigi/mbuild-all.sh -- pedantic naming 2011-05-23 04:52:29 +00:00
zzz
606300a042 * GeoIP: Read countries.txt in UTF-8 2011-05-22 18:36:08 +00:00
zzz
96cf598691 javadoc 2011-05-22 18:34:41 +00:00
zzz
6b923c7251 Fix build error that omitted local jetty patches from org.mortbay.jetty.jar;
affected 0.8.4 and 0.8.6 installers. Include jar in the updater for the next release.
        Thx KYTV.
2011-05-22 18:33:51 +00:00
zzz
18e57d19db doc update 2011-05-22 14:31:56 +00:00
45f3020924 mbuild.sh document and fixes, mbuild-all.sh add cpu types 2011-05-21 18:26:10 +00:00
zzz
d8a3cb0d58 change build script to GMP 4.3.2 2011-05-21 17:09:30 +00:00
b5dc9b6f5a Update geoip database and country list 2011-05-21 01:07:03 +00:00
zzz
38a6e6b212 restore old cpuid assembly for x64 2011-05-20 16:26:40 +00:00
zzz
627519e69c disable debug 2011-05-20 16:25:46 +00:00
zzz
2f2e0e539a history for props, -1 2011-05-20 14:23:31 +00:00
zzz
e42b78e177 propagate from branch 'i2p.i2p.zzz.naming' (head 9626e0df682c8d5f706d2c814158ba451f3ebeb5)
to branch 'i2p.i2p' (head a3969e6c9c4fd5bfd69cd716ce0df191ad2af634)
2011-05-20 14:12:07 +00:00
zzz
4b19801cdb try to prevent out-of-order logging at shutdown 2011-05-20 14:09:36 +00:00
zzz
3d76354cbb fixup after prop 2011-05-20 13:55:13 +00:00
zzz
e2c98ac134 propagate from branch 'i2p.i2p.zzz.jrobin159' (head 08df645290d8e156d88930ddaf71b3f3d8af419d)
to branch 'i2p.i2p' (head 69c9e6bd0c6894c335f7d9892aa28ac7d6389907)
2011-05-20 13:52:35 +00:00
zzz
d4fe76afee hide graph link in summary bar when disabled 2011-05-20 13:47:09 +00:00
zzz
3352c45517 - Rewrite cpuid.c so it builds with PIC (source only, binary not updated yet) 2011-05-20 13:25:19 +00:00
zzz
0e719b8eb0 fixup after prop 2011-05-20 13:17:04 +00:00
zzz
ff520b74dc propagate from branch 'i2p.i2p.libgmp' (head 41a57954f7e78e57f8eb5e30e8ebde7fd75b15dc)
to branch 'i2p.i2p' (head d174e772ebd4f3e3eac5c9b5abd7f736c2527eb2)
2011-05-20 13:13:26 +00:00
zzz
48bf618ae5 final 2011-05-20 12:49:29 +00:00
zzz
d6c1202e4b summary bar tweak 2011-05-20 12:48:58 +00:00
zzz
20452c9387 * Certificate: Fix creation bug; improve router cert generation 2011-05-20 12:46:50 +00:00
zzz
64a753116b * i2ptunnel: Fix server-side stripping of X-Accept-encoding 2011-05-20 12:43:50 +00:00
5ce439ffc4 merge of '97f5690455a3a74e68056739ea7145c8059454c6'
and 'e01e159c9825a36e8e640bb3cf8d0f1200b1be2f'
2011-05-19 05:47:02 +00:00
00f2721640 upd 2011-05-19 05:44:13 +00:00
454a310bbe make translation more castillian 2011-05-18 21:40:11 +00:00
18952f5109 upd routerconsole messages_fr.po 2011-05-18 11:37:39 +00:00
zzz
7377086aae 0.8.6 2011-05-16 19:58:19 +00:00
zzz
9f7cc9d887 add update host 2011-05-13 21:04:58 +00:00
zzz
ffa9ea9cd2 Increase min floodfills; decrease min routerinfo expiration 2011-05-13 20:13:56 +00:00
zzz
f9654661bb * Use partitions of fast tier for various hops of client tunnels; minor cleanups 2011-05-11 14:40:55 +00:00
zzz
5ce06d02b4 the rest of -2 2011-05-06 12:35:19 +00:00
zzz
c356792d02 * Tunnels and profiles:
- Increase max fast and high-cap tier sizes
      - Slow profile eval cycle after sufficient uptime
      - Fix bug which started a new build after a successful build
      - Misc. cleanups
2011-05-06 01:10:28 +00:00
90642a8ab5 warning 2011-05-05 01:59:20 +00:00
dev
0ae798d840 added simple release checklist file 2011-05-04 22:09:09 +00:00
zzz
6199e7b74c oops fix path to newly tagged files 2011-05-03 13:15:13 +00:00
1e9ac05b63 merge of '83e7567c0dbdabe57c21a0bfdc9d70acbbc71463'
and 'f783d7f664254691074c1542a6d8937731e2b503'
2011-05-02 16:24:54 +00:00
ed338d9cfa minor tweak to es 2011-05-02 16:24:48 +00:00
a84e6f7854 typos 2011-05-02 11:23:01 +00:00
zzz
fe21748b2d -1 2011-04-28 18:46:09 +00:00
zzz
8b184f8c03 one more zero-length torrent check 2011-04-28 18:05:03 +00:00
zzz
5ed22d5c16 cleanups 2011-04-28 18:04:31 +00:00
zzz
525e0b4518 tag peers.jsp UPnP text 2011-04-28 18:03:18 +00:00
zzz
e8d94982e4 * Console: Try to prevent cascaded IllegalStateExceptions in .jsp code;
add logging for original error
2011-04-28 18:01:48 +00:00
zzz
38db0b0ff3 * UPnP: Strip trailing nulls from incoming XML to prevent
"content not allowed in trailing section" exceptions
      from stupid routers
2011-04-28 17:57:30 +00:00
e4a8b9621d site (plugin) 2011-04-25 06:29:20 +00:00
66ea1c060a merge of 'aee566a8e2250d2461203b83c7a3434b29f771f9'
and 'f6410ea071e6b154e0c14deea8ef6eaa35cb7faa'
2011-04-24 07:38:51 +00:00
50dabfec8c typo typo 2011-04-24 07:37:20 +00:00
a8722e033c tweaks es 2011-04-20 00:28:02 +00:00
1cec98d180 tweaks es 2011-04-20 00:24:37 +00:00
zzz
97bb2d81b7 0.8.5 2011-04-18 03:12:51 +00:00
9c4d107b5d update de 2011-04-16 01:22:55 +00:00
eaccd029c8 merge of '9f3e70c07e90831996f4a09177d29015e02d03a1'
and 'bfdfec0ecf3dfe56d93ab5835b3c6887743e50ac'
2011-04-16 01:22:12 +00:00
b2c90b0633 update es 2011-04-16 01:20:58 +00:00
1152e117b3 routerconsole: update russian translation 2011-04-13 17:34:36 +00:00
9f3cdeb29e typo 2011-04-11 13:49:55 +00:00
699bfb3987 typo 2011-04-11 13:23:11 +00:00
0695753084 typo 2011-04-11 13:19:21 +00:00
ef0e9ca36c typo 2011-04-11 13:05:40 +00:00
3e9e56ed28 typo 2011-04-11 12:27:22 +00:00
b16cfb9df6 typos 2011-04-11 11:24:42 +00:00
18c3430656 typos 2011-04-11 10:53:02 +00:00
94298c3678 missinfo 2011-04-11 09:19:23 +00:00
a3d22e829b encore une 2011-04-11 08:55:15 +00:00
63ecc10c5e typos 2011-04-11 08:46:32 +00:00
937ef0ea4e typo 2011-04-11 08:15:45 +00:00
zzz
428db02274 * Console: Hide iframe on mobile browsers
* DataHelper: Speed up eq() (Ticket #437)
    * HTTPServer: Strip inbound X-Accept-Encoding header
    * netdb.jsp: HTML fixes
    * Plugins: Log error when console server not found
    * Reseed: Log tweak
2011-04-10 18:22:43 +00:00
960f12d66c final tweaks 2011-04-09 01:09:16 +00:00
aea618061f final tweaks 2011-04-09 00:47:57 +00:00
3995d2b123 merge of '3ef57a4333ea11a79d106a471afe2014124dc520'
and '41944e5ee9caea1445633a41c9e0f3474aefea7e'
2011-04-09 00:20:18 +00:00
891f9b2e87 final tweaks 2011-04-09 00:16:04 +00:00
47efafa722 changes to es 2011-04-08 21:55:34 +00:00
b19006690c tweaks es 2011-04-08 19:12:05 +00:00
6acef90087 final tweak 2011-04-07 21:26:17 +00:00
5b7896d16e final tweaks after tests 2011-04-07 19:04:43 +00:00
8a74eceac3 final tweaks after tests 2011-04-07 15:04:56 +00:00
a5f576d912 final tweaks after tests 2011-04-07 14:45:25 +00:00
e0c0f2a350 final tweaks after tests 2011-04-07 14:32:14 +00:00
1ca63be423 final tweaks after tests 2011-04-07 14:31:41 +00:00
eaee55e3a9 fix the damned apostrophe and some better translations for other strings 2011-04-07 11:45:30 +00:00
1fbaf24d59 fix the damned apostrophe 2011-04-07 10:32:34 +00:00
1ada55f012 add how_fr.png 2011-04-07 10:25:06 +00:00
bcbd5bbda6 fix the damned apostrophe and some typos 2011-04-07 10:19:53 +00:00
2a982a4c47 fix the damned apostrophe 2011-04-07 09:12:17 +00:00
2061640cb6 fix the damned apostrophe and other typos 2011-04-07 09:00:15 +00:00
a4ff83c0d4 fix the damned apostrophe 2011-04-06 19:43:49 +00:00
e766202a2e fix in panel: congestion->tasks list 2011-04-06 17:34:15 +00:00
0da9c606f2 remake duck's change 2011-04-06 15:33:06 +00:00
398984009b remake duck's change 2011-04-06 15:21:36 +00:00
3e00866bdf remake duck's change 2011-04-06 15:21:15 +00:00
ac3c2bd872 remake duck's change 2011-04-06 15:02:50 +00:00
281c2f5b51 tweak 2011-04-04 20:44:18 +00:00
2e9e2e20ef tweak 2011-04-04 20:37:47 +00:00
ed131f47de tweak 2011-04-04 20:27:28 +00:00
853e5ac607 tweak 2011-04-04 20:21:21 +00:00
1cffcdb670 ttweak 2011-04-04 20:13:19 +00:00
a9b1603f9f ttweak 2011-04-04 20:08:50 +00:00
aee08287eb tweak 2011-04-04 12:31:40 +00:00
131e8f6d68 translation es update 2011-04-02 22:00:39 +00:00
c8544d016d merge of '51802b6d77791cf157cb9ef16097495772c68d12'
and '7a7f3283a6a2a69e8ed4df36c0e5a9850c8bb248'
2011-04-02 20:43:42 +00:00
8198e61acc tweaks transl8ion desktopgui 2011-04-02 20:38:25 +00:00
b41ed69b0f Adding Arabic to Transifex 2011-04-02 12:18:45 +00:00
5b2cf8b676 German translation for DesktopGUI, thanks blabla 2011-04-01 21:41:13 +00:00
5d9116965b Spanish translations, thanks punkibastardo 2011-04-01 21:29:53 +00:00
07e61d499a Fix French quoting, add to Transifex 2011-04-01 21:22:33 +00:00
9f010d80fb checked against console 2011-03-30 22:52:54 +00:00
660ba64ce1 little fixes 2011-03-30 22:45:25 +00:00
29c731d660 little fixes 2011-03-30 21:08:08 +00:00
df4714e628 little fixes 2011-03-30 20:57:34 +00:00
a7d6048748 mini tweaks 2011-03-30 20:35:27 +00:00
1a40178e8c fix 2011-03-30 20:20:14 +00:00
49ac0278f0 redo 2011-03-30 20:17:44 +00:00
4c74315411 redo 2011-03-30 20:12:09 +00:00
f992a07df9 redo 2011-03-30 20:09:42 +00:00
zzz
e62d9dfa48 more cleanups, clickable logo 2011-03-30 00:56:15 +00:00
zzz
6dd7431ccd message cleanup 2011-03-30 00:42:08 +00:00
zzz
7020bfd521 display cleanups 2011-03-30 00:19:28 +00:00
zzz
0fcf13ef73 * susidns:
- IDN toASCII improvements (old bean)
- Add 'other' filter
- Fix jsp 500s
2011-03-29 23:17:14 +00:00
zzz
9e37a5a4af * susidns:
- Enforce basic rules on host name additions
- Split up form
- IDN toASCII improvements
- Log message improvements
2011-03-29 22:46:59 +00:00
9e4e9c197b typo 2011-03-29 15:17:09 +00:00
zzz
172541a368 implement delete on details page 2011-03-29 03:29:23 +00:00
zzz
9f475c03cb fix details for published book 2011-03-29 03:02:17 +00:00
zzz
fbfffa9987 - SusiDNS cleanups
- Logging cleanups
2011-03-29 02:16:42 +00:00
8ea721696f readme_fr.html 2011-03-29 00:33:45 +00:00
3e5713e479 readme_fr.html 2011-03-29 00:05:29 +00:00
b7072d48b6 messages_fr.po & readme_fr.html 2011-03-28 22:54:26 +00:00
7feefc049c readme_fr.html 2011-03-28 22:53:58 +00:00
zzz
8ae398d786 - Isolate span read failures to that span
- Don't keep separate count of spans and levels, use BSL HashMap sizes
- Fix SkipList counts when read in
2011-03-28 20:33:57 +00:00
zzz
a818e84dcf - Cleanups, logging, checks and javadocs 2011-03-28 17:15:46 +00:00
zzz
33780ef359 - Fix FLB full check
- Cache FLB
- FLB logging, cleanups, checks
2011-03-28 14:27:19 +00:00
516216730b readme_fr.html 2011-03-28 14:25:47 +00:00
7a69024fb5 messages_fr.po & readme_fr.html 2011-03-28 13:59:46 +00:00
zzz
9fcb20a7bd - Free unused span continuation pages (big space savings)
- Less data copying during on-disk searches
2011-03-28 04:57:16 +00:00
zzz
991acd3917 fix level count init 2011-03-27 22:42:36 +00:00
zzz
f4905d2742 - Use new UTF8StringBytes
- Track number of SkipLevels in a SkipList
- More double-checks
- Caching cleanups
- Cleanups, logging, generics
2011-03-27 22:36:45 +00:00
zzz
b7b7283ff9 - Use new UTF8StringBytes
- Track number of SkipLevels in a SkipList
- More double-checks
- Cleanups, logging, generics
2011-03-27 22:19:50 +00:00
zzz
22d50dd150 require router.activePeers stat (ticket #450) 2011-03-27 19:19:41 +00:00
zzz
bc231b51b5 - Fix several bugs in removal of first or second span
- Fix bugs in flushes
- Add magic numbers for free pages and free list
- More bounds checking
- Lots of checks for double-kill / double-free
- Make some freelist errors non-fatal
- Cleanups, logging, javadocs, test code
2011-03-27 18:55:51 +00:00
4d17643064 messages_fr.po 2011-03-27 18:37:09 +00:00
0b510cdc21 fignolage help_fr & console messages_fr.po 2011-03-27 10:03:04 +00:00
a188275608 revert trac #450: need enable all stats to enable active & fast peers statsgrphs, text added in help, comments removed 2011-03-27 09:01:43 +00:00
0617ee99cd Fix: Wrong working dir when running as a Windows service 2011-03-27 01:30:30 +00:00
4fbde3a0bc better 2011-03-26 20:55:47 +00:00
9911d22ac3 transl 2011-03-26 20:54:17 +00:00
b14c17c884 add news_fr.xml .... feel free to use for tests or mtn delete 2011-03-26 17:50:54 +00:00
3fe232a535 typo 2011-03-26 16:49:29 +00:00
52a0ab5482 same for highCap 2011-03-26 15:24:23 +00:00
b3dec96e1e see trac #450 2011-03-26 15:03:26 +00:00
b639482c4a tweak 2011-03-26 10:47:16 +00:00
d68e59fb04 tweak 2011-03-26 10:03:39 +00:00
d97f991230 fix 2011-03-26 08:59:39 +00:00
cc780c23f8 merge of 'c8e4037205cbf60c898d6f6e7acaf03eec0a04ab'
and 'e596e8b965b583853015d99b62798865654e4806'
2011-03-26 07:40:17 +00:00
zzz
a7fceb644f javadoc 2011-03-26 05:50:13 +00:00
zzz
312534b635 - Change disk format to add magic number to all pages
- Change blockfile magic number to reflect new format
- Cleanups and javadocs
2011-03-26 05:27:34 +00:00
zzz
8f9f102baf - Fix several bugs with BSkipLevels persistence
- Logging and debug code
- New serializers
- Cleanups and javadocs
2011-03-26 02:40:17 +00:00
26cc6a26b8 add 2011-03-26 02:38:34 +00:00
bcf9d59c82 fix 2011-03-26 01:49:09 +00:00
cf7e922dcd merge of '71dfdcd2d4d32f1ab1d0f8aa795af4e2520362dc'
and '98c75b36461d2528cd3135f43f759440d3183acc'
2011-03-26 00:33:21 +00:00
ba67bb9412 fix 2011-03-26 00:29:00 +00:00
1271e03192 fix 2011-03-25 23:15:40 +00:00
cdd986c56b update translation de 2011-03-25 22:55:37 +00:00
ea86b6880f fix 2011-03-25 22:19:29 +00:00
d47de894ab fix 2011-03-25 19:54:59 +00:00
109bd978de fix 2011-03-25 19:41:25 +00:00
25d2ce65e2 add 2011-03-25 17:20:18 +00:00
07b3ebefc1 '->\' 2011-03-25 14:53:18 +00:00
e255de6f72 '->\' 2011-03-25 14:20:33 +00:00
76bbc604ae ? 2011-03-25 11:09:59 +00:00
103bde8a32 ? 2011-03-25 11:09:12 +00:00
57140d2655 add 2011-03-25 10:14:50 +00:00
f61108bbae add 2011-03-25 09:14:26 +00:00
05a3738fdb refilled 2011-03-25 08:56:53 +00:00
ceb631719b purged 2011-03-25 08:35:43 +00:00
zzz
078056f163 implement last-modified 2011-03-24 22:07:19 +00:00
zzz
1adb3d19c7 - Better serializer error handling and logging
- Automatic corruption repair in blockfile
- Automatic removal of bad entries in BFNS
- Use unsigned shorts to extend max lengths to 65535
- Check max length
- Throw IOE on negative ints
- Tweak fromProperties() exceptions
- Fix DataHelper encoding issues (ticket #436)
- CSS tweaks
2011-03-24 21:51:20 +00:00
b5cfe00ba5 new 2011-03-24 21:22:46 +00:00
46b2fd2749 new 2011-03-24 21:14:12 +00:00
f1d1a80f4e new 2011-03-24 21:03:08 +00:00
f3a30276f3 new 2011-03-24 20:55:15 +00:00
a9579cdd87 new 2011-03-24 20:45:52 +00:00
2d4c3453b7 new 2011-03-24 20:33:18 +00:00
1f58125eed new 2011-03-24 20:25:54 +00:00
fb36da7669 new 2011-03-24 20:19:26 +00:00
fa1820786a new 2011-03-24 20:11:18 +00:00
655d0ad77e new 2011-03-24 20:10:53 +00:00
0098816866 new 2011-03-24 18:39:32 +00:00
6e08fd614a after antpoupdate 2011-03-24 16:53:10 +00:00
0680725582 upd 2011-03-24 15:37:38 +00:00
0cb10f9bb1 upd 2011-03-24 15:08:14 +00:00
zzz
7751661f3d basic IDN support 2011-03-24 05:30:33 +00:00
zzz
ca5484a984 - Add details page in susidns
- Add source in Daemon
- Honor list property in BFNS.lookup()
2011-03-24 03:00:47 +00:00
f7beb5d68e initial trsl 2011-03-24 01:47:41 +00:00
zzz
d6999a3327 * DataHelper:
- Undeprecate fromProperties() and toProperties()
      - Undeprecate BOOLEAN_FALSE and BOOLEAN_TRUE
      - Fix fromProperties() and toProperties() to correctly throw DataFormatExceptions
      - Add sort option
      - Efficiency improvements in writeProperties(), toProperties(), storeProps(), and toString()
2011-03-23 21:44:38 +00:00
541ff01fd1 merge of '6467dc867b03e6be51ac21be14d7f8cbdadc2bd2'
and 'b30b38d7e36009a6ffcdbc0c6405a97703d29128'
2011-03-23 20:26:25 +00:00
zzz
c85931cbc5 log tweaks 2011-03-23 02:22:19 +00:00
zzz
7e0d0e2b01 - Implement getNames()
- Use getNames() for merging to hosts.txt naming services to avoid O(n**2)
- Fix naming service selection
- Don't merge from master book unless publishing
- Add naming service and direct config options
2011-03-22 22:10:15 +00:00
f289be908c added UNanted susidns messages_fr.po. Please jdk guru initialize, aka antize it so I can translate. I just changed one header line 2011-03-22 22:06:12 +00:00
42e9fd9431 upd snark_fr.po 2011-03-22 21:59:14 +00:00
zzz
5dc9214296 - Iterate through eepgetted subscription file instead of loading the whole thing into memory 2011-03-22 18:20:44 +00:00
086bad4b47 upd messages-fr.po 2011-03-22 16:31:20 +00:00
22d66131f3 upd messages-fr.po 2011-03-22 16:23:59 +00:00
zzz
311bb7a4b6 propagate from branch 'i2p.i2p' (head 6467dc867b03e6be51ac21be14d7f8cbdadc2bd2)
to branch 'i2p.i2p.zzz.naming' (head ed37752523387104764b68a1deaaedb5e707e827)
2011-03-22 14:28:16 +00:00
8b10720b23 upd messages-fr.po 2011-03-22 11:06:18 +00:00
zzz
6f296a6f76 -8 2011-03-22 02:12:03 +00:00
zzz
61590d39e0 merge of '60c5cb17c0406b6e6e547489f9ea8ef3c290e262'
and 'ea425725295fb82fd45d0a93ba521f8695fa88a5'
2011-03-22 02:11:30 +00:00
zzz
c7a574fe01 final 2011-03-22 02:08:03 +00:00
zzz
1b2519cfb8 - Improved error handling
- Disable graphs on JVMs that crash
2011-03-22 01:59:52 +00:00
zzz
9c02aab4fb oops remove newline 2011-03-21 18:37:26 +00:00
c89f752ccc Update Dutch translation for routerconsole 2011-03-21 18:34:49 +00:00
zzz
40fd4ccd15 Stats:
- Refactor handling of required stats
    - Shorten description of required stats
    - Improve save messages on configstats.jsp
    - Change bw.sendBps and bw.receiveBps stats to bytes, not Kbytes
    - Expires directive for graphs
2011-03-21 18:14:58 +00:00
4c0a4a2296 Update english routerconsole tags 2011-03-21 18:06:58 +00:00
zzz
ddddc686fe propagate from branch 'i2p.i2p' (head 60c5cb17c0406b6e6e547489f9ea8ef3c290e262)
to branch 'i2p.i2p.zzz.jrobin159' (head 330a4f9652fe5f67e6e9998f5c0a87c7ef163764)
2011-03-21 14:29:03 +00:00
zzz
642376b0b6 HTML fixes 2011-03-21 14:27:46 +00:00
zzz
3ba9f872ed fix manifest error 2011-03-20 18:28:29 +00:00
zzz
bfb4560dc2 maxMemory() fixes for silly GNU returning Long.MAX_VALUE 2011-03-20 18:14:30 +00:00
zzz
fa8f2290af set firstHeardAbout; tweak dump order 2011-03-20 13:34:14 +00:00
zzz
c0422134f9 * i2psnark: Fix peers stuck at uninteresting after magnet fetch 2011-03-19 18:46:18 +00:00
zzz
b11516f758 remove cache directives 2011-03-19 18:34:39 +00:00
zzz
14986fbfa1 * Profiles:
- Nicer profile dump
      - More efficient profile lookup for display
      - Fix dumpprofile NPE
      - Change file suffix from .dat to .txt.gz
2011-03-19 17:19:54 +00:00
zzz
34d951aa6b recognize links as a text browser 2011-03-19 16:40:10 +00:00
zzz
f96342d33a backport equals() fix 2011-03-19 16:39:22 +00:00
zzz
5eb6bf1b1d change i2ptunnel clients to 3 hops for new installs 2011-03-19 16:39:04 +00:00
zzz
295e1daa22 test scripts update 2011-03-19 16:37:53 +00:00
zzz
cf0d2197b8 - Persistent option on GUI
- Fix HTML errors
- Refresh improvements
- Fix Rate.equals() bug
- More cleanups
2011-03-18 15:49:58 +00:00
zzz
79358f4271 notes and tweaks 2011-03-18 00:47:14 +00:00
zzz
12f3634f96 more rows when persistent 2011-03-17 23:25:38 +00:00
zzz
033dee0216 - Persistent RRD
- Restart line in graphs
- Restore zh fonts in graphs
2011-03-17 21:13:52 +00:00
zzz
1324eaf056 cleanups and javadoc 2011-03-17 17:16:28 +00:00
zzz
2e5e3b9d40 better error messages, fix NPE, comment out template handling 2011-03-17 16:16:50 +00:00
zzz
ef26accde0 jrobin 1.5.9.1
sha1sum 7d76f5cdec625fd1ce21acc0e46d286fbd6d307f
Released 2008-09-05
Downloaded from http://sourceforge.net/projects/jrobin/files/jrobin/1.5.9/
License: LGPL 2.1

It appears that the only difference from 1.5.9 is it was compiled with Java 5
instead of Java 6. The 1.5.9 jars out there also contain the large font .ttf files,
which are not in 1.5.9.1.

The only announcement I could find about 1.5.9.1 is here:
http://opennms.530661.n2.nabble.com/Am-I-missing-something-td841945.html

The following directories are dropped from the jar during the build process:
org/jrobin/cmd/
org/jrobin/convertor/
org/jrobin/inspector/
2011-03-17 16:03:27 +00:00
zzz
8461beba1c 1st cut 2011-03-17 02:07:08 +00:00
zzz
b93e3dfb55 cleanups and permissions 2011-03-16 18:33:56 +00:00
zzz
5ef1dd87a5 javadoc fix 2011-03-16 18:14:51 +00:00
zzz
07860d018c add b32 links to susidns; add source property for additions via susidns 2011-03-16 17:28:10 +00:00
zzz
ce5ce12e3b * Naming services:
- Refactor caching
    - Logging, caching, shutdown cleanup and fixes
2011-03-16 16:11:54 +00:00
zzz
02c4bbfc58 fix filtering 2011-03-16 03:01:32 +00:00
zzz
bf613448d7 susidns/hoststxtNS compatibility fixes 2011-03-16 01:50:22 +00:00
zzz
5095e8a1d6 naming service shutdown stuff 2011-03-16 00:37:54 +00:00
zzz
0352ca3ef6 * Naming service, addressbook, susidns:
- Replace img hack for susidns requesting addressbook update
      with registration and request through the NamingService
2011-03-15 23:16:44 +00:00
zzz
12c5b9c21c * Naming services, addressbook, susidns:
- Fix search capability
    - Fix result count and view within results
    - Fix published address book
    - Fix ngettext
    - Cache size
    - Fix 0-9 filter
    - Addressbook updates via API, except for published
2011-03-15 21:52:48 +00:00
be4be9716d readme tweaks 2011-03-13 12:39:52 +00:00
ac5785c796 update susimail de translation 2011-03-13 11:32:43 +00:00
e6b24277b6 readme tweaks 2011-03-13 11:06:33 +00:00
dca9f32d3f Make the actual installation the last step before the "Done" screen 2011-03-12 22:19:05 +00:00
21a3657da5 Add NT service as an installer option on Windows 2011-03-12 21:53:55 +00:00
zzz
3f141e72b8 ngettext fixes thx duck 2011-03-12 21:32:29 +00:00
e3a81f6091 Susimail: use ngettext, fix typo (thanks m1xxy) 2011-03-12 21:00:04 +00:00
zzz
3ecc38cc9c -6 2011-03-12 18:03:32 +00:00
zzz
b23f278c3f ngettext cleanups 2011-03-12 18:00:58 +00:00
zzz
e47afffd09 * Console: Fix HTML errors in
configpeer.jsp, configtunnels.jsp, configupdate.jsp
2011-03-12 17:32:15 +00:00
zzz
0f91899aa9 * Console: Fix HTML errors in form message box,
logs.jsp, netdb.jsp, profiles.jsp, stats.jsp
2011-03-12 16:11:10 +00:00
zzz
8e672ea548 * LogWriter: Prevent NPE after permissions fail 2011-03-12 16:09:57 +00:00
zzz
cfc17d59b4 * BuildHandler: Loop double-check 2011-03-12 16:08:52 +00:00
zzz
46e8add16a * Blocklist: Add bogons since they won't change any more 2011-03-12 16:08:11 +00:00
7f616f20ae Susimail fix typo 2011-03-12 02:37:18 +00:00
133017d2db Susimail translation de 2011-03-12 02:29:13 +00:00
ee6a058602 merge of '2800e8520ddd9ac3f56053467ccfb76cde381974'
and '5c35adb4725a7a6f8145b1f5ee552729a691706d'
2011-03-12 02:26:14 +00:00
6bbdb4fc03 merge of 'ca5b19055e887994435b0eb35978484f2489bb6e'
and 'f2d5735e0701a2b5b380f0967281811b26e26de4'
2011-03-12 02:20:39 +00:00
5def26ab93 Add Susimail to Transifex config 2011-03-11 22:23:25 +00:00
1657f151f6 Update history 2011-03-11 21:53:18 +00:00
a5b55728ba I18N for susimail, including dutch translation. 2011-03-11 21:47:00 +00:00
zzz
8b737b4adb static 2011-03-11 02:31:10 +00:00
zzz
f4e92572eb more generics 2011-03-11 02:18:15 +00:00
zzz
b048b016ad generics 2011-03-11 02:01:20 +00:00
zzz
41fc9cf4ca reverseLookup improvements 2011-03-11 01:11:18 +00:00
zzz
7edbd3ad0a * HostsTxtNamingService:
- Add getEntries() and size() support
2011-03-11 00:29:34 +00:00
zzz
de815e271c * Blockfile:
- More query options
    - More exception logging
    - Fix lookup infinite loop
    - Fix lookup NPE
  * SusiDNS:
    - Refactoring for new NamingService API
    - Initial conversion to new NamingService API
      (still needs work)
    - Fix lots of HTML warnings
    - Some Java 5 cleanup
2011-03-10 23:06:13 +00:00
zzz
ad24f1438f propagate from branch 'i2p.i2p' (head ca5b19055e887994435b0eb35978484f2489bb6e)
to branch 'i2p.i2p.zzz.naming' (head e71d7dc813c07bb2b6798ab74099efdfc1754f47)
2011-03-10 17:59:35 +00:00
zzz
b6a0426477 * logs.jsp: Fix NPE (ticket #430) 2011-03-10 14:04:16 +00:00
zzz
f71dfe50f9 * eepget: Don't set X-Accept-Encoding header (ticket #422) 2011-03-09 17:57:48 +00:00
zzz
6b6aaab881 * configui.jsp: Fix lang setting broken by previous nonce change
* Console: Consolidate nonce handling
2011-03-09 17:16:28 +00:00
zzz
8bbcb0b337 split up form, fix HTML warnings 2011-03-09 15:56:23 +00:00
zzz
a1032abc92 align tables 2011-03-09 15:55:52 +00:00
zzz
380c1e5053 efficiently use entropy in padding 2011-03-09 15:55:00 +00:00
zzz
21dbee03f1 history for prop 2011-03-08 13:34:31 +00:00
zzz
f4ca3976d5 propagate from branch 'i2p.i2p.zzz.test4' (head 7b50b6c3d48da68078a86a53e55e2c18f55685e8)
to branch 'i2p.i2p' (head ebce577e19b70c281daacc5277f98e9bb2bb9630)
2011-03-08 13:31:57 +00:00
zzz
b02fe536bc * Console:
- Parameterize download button tags (ticket #425)
      - Clean up summary bar HTML warnings
      - Just display a summary bar link for text browsers
      - Move welcome div from the readme files to index.jsp
      - Require a nonce to change language
2011-03-08 03:07:02 +00:00
zzz
f9b2c0bc63 * i2psnark:
- More efficient metainfo handling, reduce instantiations
      - Improved handling of storage errors
      - Improved handling of duplicate file names
      - More metainfo sanity checks
      - Metadata transfer error handling improvements
      - Code cleanup, remove dead and duplicated code
2011-03-08 03:01:02 +00:00
6e607e6bfe s/bit/bytes 2011-03-04 18:52:50 +00:00
0e854623c1 Last update of Arabic translation 2011-03-04 17:51:03 +00:00
21c65475f9 Update Arabic translation 2011-03-03 21:14:24 +00:00
97c36cc54e Update Arabic translation of router console 2011-03-02 22:39:14 +00:00
zzz
b30e1f5ba9 two more simple test scripts 2011-03-02 19:31:18 +00:00
zzz
b2d4a799d5 fix reversions after merge 2011-03-02 18:31:48 +00:00
zzz
9030b64dc8 merge of 'ae690eef1560c4b0cbabfd7f75a663bac6b6ee99'
and 'd88d323de60e5ba66e1c96e2d11f91de9029b27d'
2011-03-02 18:24:18 +00:00
zzz
cb707785cc * OutNetMessage: Remove dead code
* Tunnel cleanups, final, javadoc
2011-03-02 17:27:02 +00:00
zzz
f938cc7b0c * BuildHandler:
- Limit request queue size
      - Concurrent request queue
      - Remove dead code for queued rely handling
2011-03-02 17:18:37 +00:00
cacd0f898d merge of '2e344d5a40af5ff5f653e5bb911a2a693430d887'
and '7d56ae866ee2ea98e7bd34a9877f002821b4c407'
2011-02-27 20:02:29 +00:00
f8fffb5d20 merge of '1128186f23d4c02c548fa9253638806164f51256'
and '4abd29865b0fb8d04e5374f13c7d659c3d6939d4'
2011-02-27 20:02:27 +00:00
9cd0e53d0f update Arabic translation 2011-02-27 20:02:11 +00:00
b0daab601a merge of '3e32ba6e66f58b4ac347c39ab58f626c9b917f38'
and 'c68baba7320228bca1a46b463158f09ed6535aea'
2011-02-27 19:55:58 +00:00
291b70036a explicit merge of 'e6c9327ff1ba8469394ea059c363542418c60e8f'
and '3e32ba6e66f58b4ac347c39ab58f626c9b917f38'
2011-02-27 18:17:27 +00:00
bfad5889ad update de translation, small change to pt snark by user 2011-02-27 18:06:51 +00:00
zzz
a3fb49adcb add missing files; new API in blockfile NS 2011-02-27 14:49:04 +00:00
e990d98dab rollback the readme I commited accidentally to hamada's version.
fix flagbox
2011-02-27 04:03:37 +00:00
zzz
c269546c08 stub out new API, needs testing 2011-02-22 23:39:51 +00:00
zzz
258c260601 fix SkipIterator 2011-02-21 21:35:01 +00:00
zzz
f11a543233 * Clock: Cleanups and javadocs
* EepGet: Cleanups and javadocs
    * Reseed: Use the reseeder as a clock source
2011-02-11 23:59:10 +00:00
zzz
ad3342aefb exception cleanup 2011-02-08 14:26:46 +00:00
zzz
54fdfd823b - Drop deprecated NamingServices
- Add caching and b32 support to DummyNamingService
    - BlockfileNamingService Cleanups
2011-02-08 03:29:18 +00:00
zzz
ba9c7015fe blockfile naming service 2011-02-08 00:46:47 +00:00
zzz
208db9a673 initial blockfile mods 2011-02-08 00:45:23 +00:00
zzz
7f10a67804 BlockFile as downloaded 2011-02-08 00:41:33 +00:00
zzz
08d24b059a remove nativeDoubleValue(), update jbigi README 2011-01-18 14:05:26 +00:00
zzz
1811989089 unbundle jbigi.jar, create at build time 2011-01-11 00:44:36 +00:00
875 changed files with 205945 additions and 60574 deletions

View File

@ -22,3 +22,5 @@ _jsp\.java$
~$
/build/
/classes/
^debian/copyright
override.properties

View File

@ -1,47 +1,110 @@
[I2P.i2ptunnel]
source_file = apps/i2ptunnel/locale/messages_en.po
source_lang = en
trans.ar = apps/i2ptunnel/locale/messages_ar.po
trans.da = apps/i2ptunnel/locale/messages_da.po
trans.de = apps/i2ptunnel/locale/messages_de.po
trans.es = apps/i2ptunnel/locale/messages_es.po
trans.fr = apps/i2ptunnel/locale/messages_fr.po
trans.it = apps/i2ptunnel/locale/messages_it.po
trans.nl = apps/i2ptunnel/locale/messages_nl.po
trans.ru = apps/i2ptunnel/locale/messages_ru.po
trans.sv_SE = apps/i2ptunnel/locale/messages_sv.po
trans.vi = apps/i2ptunnel/locale/messages_vi.po
trans.zh_CN = apps/i2ptunnel/locale/messages_zh.po
[I2P.routerconsole]
source_file = apps/routerconsole/locale/messages_en.po
source_lang = en
trans.ar = apps/routerconsole/locale/messages_ar.po
trans.da = apps/routerconsole/locale/messages_da.po
trans.de = apps/routerconsole/locale/messages_de.po
trans.es = apps/routerconsole/locale/messages_es.po
trans.fi = apps/routerconsole/locale/messages_fi.po
trans.fr = apps/routerconsole/locale/messages_fr.po
trans.it = apps/routerconsole/locale/messages_it.po
trans.nl = apps/routerconsole/locale/messages_nl.po
trans.pl = apps/routerconsole/locale/messages_pl.po
trans.ru = apps/routerconsole/locale/messages_ru.po
trans.sv_SE = apps/routerconsole/locale/messages_sv.po
trans.uk_UA = apps/routerconsole/locale/messages_uk.po
trans.vi = apps/routerconsole/locale/messages_vi.po
trans.zh_CN = apps/routerconsole/locale/messages_zh.po
[I2P.susidns]
source_file = apps/susidns/locale/messages_en.po
source_lang = en
trans.de = apps/susidns/locale/messages_de.po
trans.nl = apps/susidns/locale/messages_nl.po
trans.ru = apps/susidns/locale/messages_ru.po
trans.zh_CN = apps/susidns/locale/messages_zh.po
[I2P.i2psnark]
source_file = apps/i2psnark/locale/messages_en.po
source_lang = en
trans.ar = apps/i2psnark/locale/messages_ar.po
trans.de = apps/i2psnark/locale/messages_de.po
trans.es = apps/i2psnark/locale/messages_es.po
trans.fr = apps/i2psnark/locale/messages_fr.po
trans.it = apps/i2psnark/locale/messages_it.po
trans.nl = apps/i2psnark/locale/messages_nl.po
trans.pl = apps/i2psnark/locale/messages_pl.po
trans.pt = apps/i2psnark/locale/messages_pt.po
trans.ru = apps/i2psnark/locale/messages_ru.po
trans.sv_SE = apps/i2psnark/locale/messages_sv.po
trans.vi = apps/i2psnark/locale/messages_vi.po
trans.zh_CN = apps/i2psnark/locale/messages_zh.po
[I2P.susidns]
source_file = apps/susidns/locale/messages_en.po
source_lang = en
trans.ar = apps/susidns/locale/messages_ar.po
trans.da = apps/susidns/locale/messages_da.po
trans.de = apps/susidns/locale/messages_de.po
trans.es = apps/susidns/locale/messages_es.po
trans.fr = apps/susidns/locale/messages_fr.po
trans.it = apps/susidns/locale/messages_it.po
trans.nl = apps/susidns/locale/messages_nl.po
trans.pl = apps/susidns/locale/messages_pl.po
trans.ru = apps/susidns/locale/messages_ru.po
trans.sv_SE = apps/susidns/locale/messages_sv.po
trans.uk_UA = apps/susidns/locale/messages_uk.po
trans.vi = apps/susidns/locale/messages_vi.po
trans.zh_CN = apps/susidns/locale/messages_zh.po
[I2P.desktopgui]
source_file = apps/desktopgui/locale/messages_en.po
source_lang = en
trans.ar = apps/desktopgui/locale/messages_ar.po
trans.da = apps/desktopgui/locale/messages_da.po
trans.de = apps/desktopgui/locale/messages_de.po
trans.es = apps/desktopgui/locale/messages_es.po
trans.fr = apps/desktopgui/locale/messages_fr.po
trans.it = apps/desktopgui/locale/messages_it.po
trans.nl = apps/desktopgui/locale/messages_nl.po
trans.pl = apps/desktopgui/locale/messages_pl.po
trans.ru = apps/desktopgui/locale/messages_ru.po
trans.sv_SE = apps/desktopgui/locale/messages_sv.po
trans.uk_UA = apps/desktopgui/locale/messages_uk.po
trans.vi = apps/desktopgui/locale/messages_vi.po
trans.zh_CN = apps/desktopgui/locale/messages_zh.po
[I2P.susimail]
source_file = apps/susimail/locale/messages_en.po
source_lang = en
trans.de = apps/susimail/locale/messages_de.po
trans.es = apps/susimail/locale/messages_es.po
trans.fr = apps/susimail/locale/messages_fr.po
trans.it = apps/susimail/locale/messages_it.po
trans.nl = apps/susimail/locale/messages_nl.po
trans.ru = apps/susimail/locale/messages_ru.po
trans.sv_SE = apps/susimail/locale/messages_sv.po
trans.pl = apps/susimail/locale/messages_pl.po
trans.vi = apps/susimail/locale/messages_vi.po
trans.zh_CN = apps/susimail/locale/messages_zh.po
[I2P.debconf]
source_file = debian/po/templates.pot
source_lang = en
trans.de = debian/po/de.po
trans.es = debian/po/es.po
trans.pl = debian/po/pl.po
trans.ru = debian/po/ru.po
trans.sv_SE = debian/po/sv.po
trans.uk_UA = debian/po/uk.po
[main]
host = http://www.transifex.net

View File

@ -1,4 +1,4 @@
Headless I2P installation instructions
Headless (console mode) I2P installation instructions
1) java -jar i2pinstall.exe -console (you've already done this)
@ -6,9 +6,9 @@ This will run the installer in text mode, including running the postinstall.sh
script. After that, you may run 'sh i2prouter start'
which will start the router and attempt to launch a browser.
If you do not have an X server running, the browser launch will probably fail, and
If you do not have an X server running, the browser launch may fail, and
you may use:
lynx http://localhost:7657/index.jsp
lynx http://localhost:7657/
to configure the router.
If you're having trouble, swing by http://forum.i2p2.de/, check the
@ -24,22 +24,22 @@ edit the files i2prouter (Linux) and wrapper.config (Linux and Windows)
where there are comments labeled "PORTABLE". Do this before you
run I2P for the first time.
To run I2P explicitly:
To start I2P:
(*nix): sh i2prouter start
(win*): I2P.exe
(Platforms unsupported by the wrapper - PPC, ARM, etc): sh runplain.sh
(non-x86 platforms PPC, ARM, etc): sh runplain.sh
To stop the router (gracefully):
lynx http://localhost:7657/configservice.jsp ("Shutdown gracefully")
To stop I2P (gracefully):
lynx http://localhost:7657/summaryframe (click "Shutdown")
To stop the router (immediately):
To stop I2P immediately:
sh i2prouter stop
To uninstall I2P:
rm -rf $i2pInstallDir
rm -rf $I2PInstallDir ~/.i2p
Supported JVMs:
Windows: Latest available from http://java.sun.com/ (1.5+ supported)
Linux: Latest available from http://java.sun.com/ (1.5+ supported)
FreeBSD: Sun 1.5-compatible (NIO required)
various: http://www.kaffe.org/ Sun 1.5-compatible (NIO required)
Windows: Latest available from http://java.com/download (1.5+ supported)
Linux: Latest available from http://java.com/download (1.5+ supported)
FreeBSD: 1.5-compatible (NIO required)
Other operating systems and JVMs: See http://trac.i2p2.de/wiki/java

View File

@ -1,8 +1,8 @@
I2P source installation instructions
Prerequisites to build from source:
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
The SDK must have Pack200 support (java.util.jar.Pack200)
Java SDK (preferably Oracle/Sun or OpenJDK) 1.6.0 or higher
Non-linux operating systems and JVMs: See http://trac.i2p2.de/wiki/java
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/
@ -24,10 +24,32 @@ From there, you can run the headless (console mode) installer:
Or run the GUI installer:
java -jar i2pinstall.exe
Or move the update file into an existing installation directory and restart.
Or move the i2pupdate.zip file into an existing installation directory and restart.
To start I2P:
(*nix): sh i2prouter start
(win*): I2P.exe or i2prouter.bat
(non-x86 platforms PPC, ARM, etc): sh runplain.sh
To install I2P as a system service:
(*nix) sh i2prouter install
(win*) install_i2p_service_winnt.bat
To uninstall I2P as a system service:
(*nix) sh i2prouter remove
(win*) uninstall_i2p-service_winnt.bat
To stop I2P (gracefully):
lynx http://localhost:7657/summaryframe (click "Shutdown")
To stop I2P immediately:
sh i2prouter stop
To uninstall I2P:
rm -rf $I2PInstallDir ~/.i2p
Supported JVMs:
Windows: Latest available from http://java.sun.com/ (1.5+ supported)
Linux: Latest available from http://java.sun.com/ (1.5+ supported)
FreeBSD: Sun 1.5-compatible (NIO required)
various: http://www.kaffe.org/ Sun 1.5-compatible (NIO required)
Windows: Latest available from http://java.com/download (1.5+ supported)
Linux: Latest available from http://java.com/download (1.5+ supported)
FreeBSD: 1.5-compatible (NIO required)
Other operating systems and JVMs: See http://trac.i2p2.de/wiki/java

View File

@ -29,7 +29,7 @@ POSSIBILITY OF SUCH DAMAGES.
LICENSES
--------
Core:
Core (i2p.jar):
Public domain except as listed below:
ElGamal and DSA code:
@ -41,8 +41,8 @@ Public domain except as listed below:
See licenses/LICENSE-SHA256.txt
AES code:
Under the Cryptix (MIT) license, written by the Cryptix team
(That's what our website says but all our AES code looks like it is public domain)
Copyright (c) 1995-2005 The Cryptix Foundation Limited.
See licenses/LICENSE-Cryptix.txt
Crypto filters:
From the xlattice app - http://xlattice.sourceforge.net/
@ -56,10 +56,6 @@ Public domain except as listed below:
Copyright (C) 2001, 2002, Free Software Foundation, Inc.
See licenses/LICENSE-LGPLv2.1.txt
GMP 4.1.3:
Copyright 1991, 1996, 1999, 2000 Free Software Foundation, Inc.
See licenses/LICENSE-LGPLv2.1.txt
HashCash code:
Copyright 2006 Gregory Rubin grrubin@gmail.com
See licenses/LICENSE-HashCash.txt
@ -72,8 +68,12 @@ Public domain except as listed below:
Contains some code Copyright 2006 Sun Microsystems, Inc.
See licenses/LICENSE-InstallCert.txt
BlockFile:
Copyright (c) 2006, Matthew Estes
See licenses/LICENSE-BlockFile.txt
Router:
Router (router.jar):
Public domain except as listed below:
UPnP.java:
From freenet
@ -83,7 +83,7 @@ Public domain except as listed below:
Copyright (C) 2003-2006 Satoshi Konno
See licenses/LICENSE-UPnP.txt
GeoIP data free to use, courtesy http://ip-to-country.webhosting.info/
GeoIP data free to use, courtesy http://www.maxmind.com/
Installer:
@ -127,11 +127,22 @@ Installer:
Wrapper 3.1.1:
Copyright (c) 1999, 2004 Tanuki Software
Java Service Wrapper Community Edition 32-bit 3.5.9:
Copyright (C) 1999-2011 Tanuki Software, Ltd. All Rights Reserved.
See licenses/LICENSE-Wrapper.txt
Jbigi Libraries (jbigi.jar):
JNI code public domain.
GMP 4.1.3 / 4.1.4:
Copyright 1991, 1996, 1999, 2000 Free Software Foundation, Inc.
See licenses/LICENSE-LGPLv2.1.txt
GMP 4.3.2 / 5.0.2:
Copyright 1991, 1996, 1999, 2000, 2007 Free Software Foundation, Inc.
See licenses/LICENSE-LGPLv3.txt
Applications:
@ -141,7 +152,7 @@ Applications:
BOB:
Copyright (C) sponge
DWTFYWTPL
See licenses/COPYING-BOB.txt
I2PSnark:
Copyright (C) 2003 Mark J. Wielaard
@ -164,13 +175,13 @@ Applications:
By welterde.
See licenses/LICENSE-GPLv2.txt
Jetty 5.1.12:
Jetty 5.1.15:
Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
See licenses/LICENSE-Apache1.1.txt
See licenses/LICENSE-Apache2.0.txt
See licenses/NOTICE-Commons-Logging.txt
JRobin 1.4.0:
JRobin 1.5.9.1:
See licenses/LICENSE-LGPLv2.1.txt
Ministreaming Lib:
@ -183,13 +194,21 @@ Applications:
Router console:
Public domain.
Flag icons: public domain, courtesy mjames@gmail.com http://www.famfamfam.com/
Flag icons:
- Jersey and EU flag icons: public domain, courtesy Xrmap flag
collection http://www.arvernes.com/wiki/index.php/Xrmap
- Guernsey flag from the Open Clip Art Library, released into the public domain
- All other flag icons: public domain, courtesy mjames@gmail.com http://www.famfamfam.com/
Silk icons: See licenses/LICENSE-SilkIcons.txt
GeoIP Data:
Copyright (c) 2003 Direct Information Pvt. Ltd. All Rights Reserved.
Copyright (c) 2008 MaxMind, Inc. All Rights Reserved.
See licenses/LICENSE-GeoIP.txt
Router Console and I2PSnark themes:
"Man with hat over face" & related images licensed under a Creative Commons 2.0 license.
Original photos by Florian Kuhlmann. http://www.flickr.com/photos/floriankuhlmann/3117758155
SAM:
Public domain.
@ -199,6 +218,8 @@ Applications:
SusiDNS:
Copyright (C) 2005 <susi23@mail.i2p>
See licenses/LICENSE-GPLv2.txt
Uses Apache Jakarta Standard Tag Library 1.1.2:
See licenses/LICENSE-Apache2.0.txt
SusiMail:
Copyright (C) 2004-2005 <susi23@mail.i2p>
@ -220,8 +241,9 @@ distributions. See the source package for the additional license information.
Admin Manager:
Public domain
Atalk:
Public domain
BOB Demos:
Copyright (C) sponge
DWTFYWTPL
Desktopgui
Copyright (c) Mathias De Maré
@ -240,7 +262,3 @@ distributions. See the source package for the additional license information.
SAM Python Library:
Public domain.
I2PSnark/Console themes:
"Man with hat over face" & related images licensed under a Creative Commons 2.0 license.
Original photos by Florian Kuhlmann. http://www.flickr.com/photos/floriankuhlmann/3117758155

View File

@ -1,9 +1,9 @@
Prerequisites to build from source:
Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
The SDK must have Pack200 support (java.util.jar.Pack200)
Java SDK (preferably Oracle/Sun or OpenJDK) 1.6.0 or higher
Non-linux operating systems and JVMs: See http://trac.i2p2.de/wiki/java
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/
from the GNU gettext package http://www.gnu.org/software/gettext/
To build:
ant pkg
@ -11,7 +11,7 @@ To build:
See INSTALL.txt or http://www.i2p2.de/download.html for installation instructions.
Documentation:
http://www.i2p2.de/
http://www.i2p2.de/how
API: run 'ant javadoc' then start at build/javadoc/index.html
Latest release:

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.i2p.router"
android:versionCode="1"
android:versionName="1.0.0">
<uses-permission android:name="android.permission.INTERNET" />
<!-- 3 = 1.5, 2 = 1.1, 1 = 1.0; would probably work with 1 but don't have a 1.0 SDK to test against -->
<uses-sdk android:minSdkVersion="2" />
<application android:label="@string/app_name">
<activity android:name=".I2PAndroid"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,38 +0,0 @@
These instructions are for a recent Android SDK (1.6 or later)..
Should also still work with a 1.5 SDK.
The build file is not compatible with the 1.1 SDK any more.
#Download the SDK from http://developer.android.com/sdk/index.html
#Unzip the android SDK in ../../
#So then the android tools will be in ../../android-sdk-linux_86/tools/
#
# now go to the available packages tab, check the box and click refresh,
# and download an SDK Platform
# Since I2P is configured to run on 1.1 or higher
# (API 2) download that one. Otherwise you must change the
# target in default.properties from android-2 to andriod-x
# where x is the API version.
# create a file local.properties with the following line:
# sdk-location=/path/to/your/android-sdk-linux_86
#then build the android apk file:
ant debug
# Create the android 1.1 (API 2) virtual device
# (don't make a custom hardware profile)
# A AVD created with the 1.5 SDK will not work with the newer tools
../../android-sdk-linux_86/tools/android create avd --name i2p --target 2
#then run the emulator:
../../android-sdk-linux_86/tools/emulator -avd i2p &
#then wait a couple minutes until the emulator is up
#then install the I2P app
ant install
#then run the debugger
../../android-sdk-linux_86/tools/ddms &
#to rebuild and reinstall to emulator:
ant reinstall

View File

@ -1,356 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name=".I2PAndroid" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contain the path to the SDK. It should *NOT* be checked in in Version
Control Systems. -->
<property file="local.properties"/>
<!-- The build.properties file can be created by you and is never touched
by the 'android' tool. This is the place to change some of the default property values
used by the Ant rules.
Here are some properties you may want to change/update:
application-package
the name of your application package as defined in the manifest. Used by the
'uninstall' rule.
source-folder
the name of the source folder. Default is 'src'.
out-folder
the name of the output folder. Default is 'bin'.
Properties related to the SDK location or the project target should be updated
using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems.
-->
<property file="build.properties"/>
<!-- The default.properties file is created and updated by the 'android' tool, as well
as ADT.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems. -->
<property file="default.properties"/>
<!-- Custom Android task to deal with the project target, and import the proper rules.
This requires ant 1.6.0 or above. -->
<path id="android.antlibs">
<pathelement path="${sdk-location}/tools/lib/anttasks.jar" />
<pathelement path="${sdk-location}/tools/lib/sdklib.jar" />
<pathelement path="${sdk-location}/tools/lib/androidprefs.jar" />
<pathelement path="${sdk-location}/tools/lib/apkbuilder.jar" />
<pathelement path="${sdk-location}/tools/lib/jarutils.jar" />
</path>
<taskdef name="setup"
classname="com.android.ant.SetupTask"
classpathref="android.antlibs"/>
<!-- Execute the Android Setup task that will setup some properties specific to the target,
and import the rules files.
To customize the rules, copy/paste them below the task, and disable import by setting
the import attribute to false:
<setup import="false" />
This will ensure that the properties are setup correctly but that your customized
targets are used.
-->
<setup import="false" />
<!--
================================================================================
New I2P rules
================================================================================
-->
<target name="buildrouter" depends="dirs" >
<!-- build router and core -->
<ant dir=".." target="buildrouter" />
<!-- router -->
<copy file="../build/router.jar" todir="${external-libs-folder}" />
<!-- core -->
<mkdir dir="tmp" />
<unjar src="../build/i2p.jar" dest="tmp/" />
<delete file="tmp/net/i2p/util/LogWriter.class" />
<!-- org.bouncycastle.crypto already in android
but we need a little trickery because our HMac is incompatible...
and the libs aren't in the SDK to compile against??? -->
<jar destfile="${external-libs-folder}/crypto.jar" >
<fileset dir="tmp/" >
<include name="org/bouncycastle/crypto/Digest.class" />
<include name="org/bouncycastle/crypto/Mac.class" />
<include name="org/bouncycastle/crypto/digests/GeneralDigest.class" />
<include name="org/bouncycastle/crypto/digests/MD5Digest.class" />
</fileset>
</jar>
<delete>
<fileset dir="tmp/" >
<include name="org/bouncycastle/crypto/Digest.class" />
<include name="org/bouncycastle/crypto/Mac.class" />
<include name="org/bouncycastle/crypto/digests/GeneralDigest.class" />
<include name="org/bouncycastle/crypto/digests/MD5Digest.class" />
</fileset>
</delete>
<!--
<delete dir="tmp/org/bouncycastle/" />
<delete file="tmp/net/i2p/crypto/HMACGenerator.class" />
-->
<delete file="tmp/org/bouncycastle/" />
<!-- lots of unneeded stuff could be deleted here -->
<jar destfile="${external-libs-folder}/i2p.jar" basedir="tmp/" />
<!-- some resources -->
<mkdir dir="res/drawable/" />
<copy file="../installer/resources/themes/console/images/i2plogo.png" todir="res/drawable/" />
<copy file="../installer/resources/blocklist.txt" tofile="res/raw/blocklist_txt" />
</target>
<target name="hackcleanup">
<delete file="${external-libs-folder}/crypto.jar" />
</target>
<!-- fix for property name change sometime after SDK 1.5 -->
<property name="android-jar" value="${android.jar}" />
<property name="android-aidl" value="${android.aidl}" />
<!--
================================================================================
From here down copied from SDK platforms/android-1.1/templates/android_rules.xml
and then modified
================================================================================
-->
<!--
This rules file is meant to be imported by the custom Ant task:
com.android.ant.AndroidInitTask
The following properties are put in place by the importing task:
android-jar, android-aidl, aapt, aidl, and dx
Additionnaly, the task sets up the following classpath reference:
android.target.classpath
This is used by the compiler task as the boot classpath.
-->
<!-- Custom tasks -->
<taskdef name="aaptexec"
classname="com.android.ant.AaptExecLoopTask"
classpathref="android.antlibs"/>
<taskdef name="apkbuilder"
classname="com.android.ant.ApkBuilderTask"
classpathref="android.antlibs"/>
<!-- Properties -->
<property name="android-tools" value="${sdk-location}/tools" />
<!-- Input directories -->
<property name="source-folder" value="src" />
<property name="gen-folder" value="gen" />
<property name="resource-folder" value="res" />
<property name="asset-folder" value="assets" />
<property name="source-location" value="${basedir}/${source-folder}" />
<!-- folder for the 3rd party java libraries -->
<property name="external-libs-folder" value="libs" />
<!-- folder for the native libraries -->
<property name="native-libs-folder" value="libs" />
<!-- Output directories -->
<property name="gen-folder" value="gen" />
<property name="out-folder" value="bin" />
<property name="out-classes" value="${out-folder}/classes" />
<property name="out-classes-location" value="${basedir}/${out-classes}"/>
<!-- out folders for a parent project if this project is an instrumentation project -->
<property name="main-out-folder" value="../${out-folder}" />
<property name="main-out-classes" value="${main-out-folder}/classes"/>
<!-- Intermediate files -->
<property name="dex-file" value="classes.dex" />
<property name="intermediate-dex" value="${out-folder}/${dex-file}" />
<!-- dx does not properly support incorrect / or \ based on the platform
and Ant cannot convert them because the parameter is not a valid path.
Because of this we have to compute different paths depending on the platform. -->
<condition property="intermediate-dex-location"
value="${basedir}\${intermediate-dex}"
else="${basedir}/${intermediate-dex}" >
<os family="windows"/>
</condition>
<!-- The final package file to generate -->
<property name="out-debug-package" value="${out-folder}/${ant.project.name}-debug.apk"/>
<!-- Tools -->
<condition property="exe" value=".exe" else=""><os family="windows"/></condition>
<property name="adb" value="${android-tools}/adb${exe}"/>
<!-- rules -->
<!-- Create the output directories if they don't exist yet. -->
<target name="dirs">
<echo>Creating output directories if needed...</echo>
<mkdir dir="${resource-folder}" />
<mkdir dir="${external-libs-folder}" />
<mkdir dir="${gen-folder}" />
<mkdir dir="${out-folder}" />
<mkdir dir="${out-classes}" />
</target>
<!-- Generate the R.java file for this project's resources. -->
<target name="resource-src" depends="dirs">
<echo>Generating R.java / Manifest.java from the resources...</echo>
<exec executable="${aapt}" failonerror="true">
<arg value="package" />
<arg value="-m" />
<arg value="-J" />
<arg path="${gen-folder}" />
<arg value="-M" />
<arg path="AndroidManifest.xml" />
<arg value="-S" />
<arg path="${resource-folder}" />
<arg value="-I" />
<arg path="${android-jar}" />
</exec>
</target>
<!-- Generate java classes from .aidl files. -->
<target name="aidl" depends="dirs">
<echo>Compiling aidl files into Java classes...</echo>
<apply executable="${aidl}" failonerror="true">
<arg value="-p${android-aidl}" />
<arg value="-I${source-folder}" />
<arg value="-o${gen-folder}" />
<fileset dir="${source-folder}">
<include name="**/*.aidl"/>
</fileset>
</apply>
</target>
<!-- Compile this project's .java files into .class files. -->
<!-- I2P add buildrouter -->
<target name="compile" depends="buildrouter, resource-src, aidl">
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
destdir="${out-classes}"
bootclasspathref="android.target.classpath">
<src path="${source-folder}" />
<src path="${gen-folder}" />
<classpath>
<fileset dir="${external-libs-folder}" includes="*.jar"/>
<pathelement path="${main-out-classes}"/>
</classpath>
</javac>
</target>
<!-- Convert this project's .class files into .dex files. -->
<!-- I2P add hackcleanup -->
<target name="dex" depends="compile, hackcleanup">
<echo>Converting compiled files and external libraries into ${out-folder}/${dex-file}...</echo>
<apply executable="${dx}" failonerror="true" parallel="true">
<!-- I2P this is a bad sign that we need this -->
<arg value="-JXmx256m" />
<arg value="--dex" />
<arg value="--output=${intermediate-dex-location}" />
<arg path="${out-classes-location}" />
<fileset dir="${external-libs-folder}" includes="*.jar"/>
</apply>
</target>
<!-- Put the project's resources into the output package file
This actually can create multiple resource package in case
Some custom apk with specific configuration have been
declared in default.properties.
-->
<target name="package-resources">
<echo>Packaging resources</echo>
<aaptexec executable="${aapt}"
command="package"
manifest="AndroidManifest.xml"
resources="${resource-folder}"
assets="${asset-folder}"
androidjar="${android-jar}"
outfolder="${out-folder}"
basename="${ant.project.name}" />
</target>
<!-- Package the application and sign it with a debug key.
This is the default target when building. It is used for debug. -->
<target name="debug" depends="dex, package-resources">
<apkbuilder
outfolder="${out-folder}"
basename="${ant.project.name}"
signed="true"
verbose="false">
<file path="${intermediate-dex}" />
<sourcefolder path="${source-folder}" />
<jarfolder path="${external-libs-folder}" />
<nativefolder path="${native-libs-folder}" />
</apkbuilder>
</target>
<!-- Package the application without signing it.
This allows for the application to be signed later with an official publishing key. -->
<target name="release" depends="dex, package-resources">
<apkbuilder
outfolder="${out-folder}"
basename="${ant.project.name}"
signed="false"
verbose="false">
<file path="${intermediate-dex}" />
<sourcefolder path="${source-folder}" />
<jarfolder path="${external-libs-folder}" />
<nativefolder path="${native-libs-folder}" />
</apkbuilder>
<echo>All generated packages need to be signed with jarsigner before they are published.</echo>
</target>
<!-- Install the package on the default emulator -->
<target name="install" depends="debug">
<echo>Installing ${out-debug-package} onto default emulator...</echo>
<exec executable="${adb}" failonerror="true">
<arg value="install" />
<arg path="${out-debug-package}" />
</exec>
</target>
<target name="reinstall" depends="debug">
<echo>Installing ${out-debug-package} onto default emulator...</echo>
<exec executable="${adb}" failonerror="true">
<arg value="install" />
<arg value="-r" />
<arg path="${out-debug-package}" />
</exec>
</target>
<!-- Uinstall the package from the default emulator -->
<target name="uninstall">
<echo>Uninstalling ${application-package} from the default emulator...</echo>
<exec executable="${adb}" failonerror="true">
<arg value="uninstall" />
<arg path="${application-package}" />
</exec>
</target>
<target name="help">
<!-- displays starts at col 13
|13 80| -->
<echo>Android Ant Build. Available targets:</echo>
<echo> help: Displays this help.</echo>
<echo> debug: Builds the application and sign it with a debug key.</echo>
<echo> release: Builds the application. The generated apk file must be</echo>
<echo> signed before it is published.</echo>
<echo> install: Installs the debug package onto a running emulator or</echo>
<echo> device. This can only be used if the application has </echo>
<echo> not yet been installed.</echo>
<echo> reinstall: Installs the debug package on a running emulator or</echo>
<echo> device that already has the application.</echo>
<echo> The signatures must match.</echo>
<echo> uninstall: uninstall the application from a running emulator or</echo>
<echo> device.</echo>
</target>
</project>

View File

@ -1,11 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-2

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, I2PAndroid"
/>
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/i2plogo"
/>
</LinearLayout>

View File

@ -1,3 +0,0 @@
logger.defaultLevel=INFO
logger.record.net.i2p.router.transport.FIFOBandwidthRefiller=ERROR
logger.record.net.i2p.stat.Rate=ERROR

View File

@ -1,22 +0,0 @@
# initial router.config
# temp directory
i2p.dir.temp=/data/data/net.i2p.router/files/tmp
i2p.dir.pid=/data/data/net.i2p.router/files/tmp
# save memory
prng.buffers=2
router.decayingBloomFilterM=20
stat.full=false
i2np.udp.maxConnections=30
# no I2CP
i2p.dummyClientFacade=true
# for now
#i2np.ntcp.enable=false
#
# UDP crashes the JVM, don't know why
#
i2np.udp.enable=false
# no COMM at all!!!
#i2p.vmCommSystem=true
# not on android
i2np.upnp.enable=false
routerconsole.geoip.enable=false

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">I2PAndroid</string>
</resources>

View File

@ -1,142 +0,0 @@
package net.i2p.router;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.os.Bundle;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.List;
import net.i2p.router.Router;
import net.i2p.router.RouterLaunch;
// import net.i2p.util.NativeBigInteger;
public class I2PAndroid extends Activity
{
static Context _context;
private static final String DIR = "/data/data/net.i2p.router/files";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_context = this; // Activity extends Context
debugStuff();
initialize();
// 300ms per run
// 5x slower than java on my server and 50x slower than native on my server
// NativeBigInteger.main(null);
}
public void onRestart()
{
System.err.println("onRestart called");
super.onRestart();
}
public void onStart()
{
System.err.println("onStart called");
super.onStart();
RouterLaunch.main(null);
System.err.println("Router.main finished");
}
public void onResume()
{
System.err.println("onResume called");
super.onResume();
}
public void onPause()
{
System.err.println("onPause called");
super.onPause();
}
public void onStop()
{
System.err.println("onStop called");
super.onStop();
// from routerconsole ContextHelper
List contexts = RouterContext.listContexts();
if ( (contexts == null) || (contexts.isEmpty()) )
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
RouterContext ctx = (RouterContext)contexts.get(0);
// shutdown() doesn't return so use shutdownGracefully()
ctx.router().shutdownGracefully(Router.EXIT_HARD);
System.err.println("shutdown complete");
}
public void onDestroy()
{
System.err.println("onDestroy called");
super.onDestroy();
}
public static Context getContext() {
return _context;
}
private void debugStuff() {
System.err.println("java.io.tmpdir" + ": " + System.getProperty("java.io.tmpdir"));
System.err.println("java.vendor" + ": " + System.getProperty("java.vendor"));
System.err.println("java.version" + ": " + System.getProperty("java.version"));
System.err.println("os.arch" + ": " + System.getProperty("os.arch"));
System.err.println("os.name" + ": " + System.getProperty("os.name"));
System.err.println("os.version" + ": " + System.getProperty("os.version"));
System.err.println("user.dir" + ": " + System.getProperty("user.dir"));
System.err.println("user.home" + ": " + System.getProperty("user.home"));
System.err.println("user.name" + ": " + System.getProperty("user.name"));
}
private void initialize() {
// Until we can edit the router.config on the device,
// copy it from the resource every time.
// File f = new I2PFile("router.config");
// if (!f.exists()) {
copyResourceToFile(R.raw.router_config, "router.config");
copyResourceToFile(R.raw.logger_config, "logger.config");
copyResourceToFile(R.raw.blocklist_txt, "blocklist.txt");
// }
// Set up the locations so Router and WorkingDir can find them
System.setProperty("i2p.dir.base", DIR);
System.setProperty("i2p.dir.config", DIR);
System.setProperty("wrapper.logfile", DIR + "/wrapper.log");
}
private void copyResourceToFile(int resID, String f) {
InputStream in = null;
FileOutputStream out = null;
System.err.println("Creating file " + f + " from resource");
byte buf[] = new byte[4096];
try {
// Context methods
in = getResources().openRawResource(resID);
out = openFileOutput(f, 0);
int read = 0;
while ( (read = in.read(buf)) != -1)
out.write(buf, 0, read);
} catch (IOException ioe) {
} catch (Resources.NotFoundException nfe) {
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
if (out != null) try { out.close(); } catch (IOException ioe) {}
}
}
}

View File

@ -1,163 +0,0 @@
package net.i2p.util;
/*
* public domain
*
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
/**
* bridge to android logging
*
* @author zzz
*/
class LogWriter implements Runnable {
private final static long CONFIG_READ_ITERVAL = 10 * 1000;
private long _lastReadConfig = 0;
private long _numBytesInCurrentFile = 0;
private OutputStream _currentOut; // = System.out
private int _rotationNum = -1;
private String _logFilenamePattern;
private File _currentFile;
private LogManager _manager;
private boolean _write;
private LogWriter() { // nop
}
public LogWriter(LogManager manager) {
_manager = manager;
}
public void stopWriting() {
_write = false;
}
public void run() {
_write = true;
try {
while (_write) {
flushRecords();
rereadConfig();
}
System.err.println("Done writing");
} catch (Exception e) {
System.err.println("Error writing the logs: " + e.getMessage());
e.printStackTrace();
}
}
public void flushRecords() { flushRecords(true); }
public void flushRecords(boolean shouldWait) {
try {
List records = _manager._removeAll();
if (records == null) return;
for (int i = 0; i < records.size(); i++) {
LogRecord rec = (LogRecord) records.get(i);
writeRecord(rec);
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
if (shouldWait) {
try {
synchronized (this) {
this.wait(10*1000);
}
} catch (InterruptedException ie) { // nop
}
}
}
}
public String currentFile() {
return _currentFile != null ? _currentFile.getAbsolutePath() : "uninitialized";
}
private void rereadConfig() {
long now = Clock.getInstance().now();
if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
_manager.rereadConfig();
_lastReadConfig = now;
}
}
private void writeRecord(LogRecord rec) {
if (rec.getThrowable() == null)
log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage());
else
log(rec.getPriority(), rec.getSource(), rec.getSourceName(), rec.getThreadName(), rec.getMessage(), rec.getThrowable());
}
public void log(int priority, Class src, String name, String threadName, String msg) {
if (src != null) {
String tag = src.getName();
int dot = tag.lastIndexOf(".");
if (dot >= 0)
tag = tag.substring(dot + 1);
android.util.Log.println(toAndroidLevel(priority),
tag,
'[' + threadName + "] " + msg);
} else if (name != null)
android.util.Log.println(toAndroidLevel(priority),
name,
'[' + threadName + "] " + msg);
else
android.util.Log.println(toAndroidLevel(priority),
threadName, msg);
}
public void log(int priority, Class src, String name, String threadName, String msg, Throwable t) {
if (src != null) {
String tag = src.getName();
int dot = tag.lastIndexOf(".");
if (dot >= 0)
tag = tag.substring(dot + 1);
android.util.Log.println(toAndroidLevel(priority),
tag,
'[' + threadName + "] " + msg +
' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
} else if (name != null)
android.util.Log.println(toAndroidLevel(priority),
name,
'[' + threadName + "] " + msg +
' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
else
android.util.Log.println(toAndroidLevel(priority),
threadName,
msg + ' ' + t.toString() + ' ' + android.util.Log.getStackTraceString(t));
}
private static int toAndroidLevel(int level) {
switch (level) {
case Log.DEBUG:
return android.util.Log.DEBUG;
case Log.INFO:
return android.util.Log.INFO;
case Log.WARN:
return android.util.Log.WARN;
case Log.ERROR:
case Log.CRIT:
default:
return android.util.Log.ERROR;
}
}
private static final String replace(String pattern, int num) {
char c[] = pattern.toCharArray();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < c.length; i++) {
if ( (c[i] != '#') && (c[i] != '@') )
buf.append(c[i]);
else
buf.append(num);
}
return buf.toString();
}
}

View File

@ -71,6 +71,7 @@
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" />

View File

@ -26,7 +26,7 @@ dist.dir=dist
dist.jar=${dist.dir}/BOB.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
excludes=**/*.html,**/*.txt
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
file.reference.i2p.jar=../../core/java/build/i2p.jar
file.reference.i2ptunnel.jar=../i2ptunnel/java/build/i2ptunnel.jar

View File

@ -51,6 +51,8 @@
<!-- unused for now, as we oddly ship addressbook as a .war -->
<target name="jar" depends="compile, changes">
<jar basedir="${build}" destfile="${dist}/${jar}">
<!-- set if unset -->
<property name="workspace.changes" value="" />
<manifest>
<attribute name="Main-Class" value="addressbook.Daemon"/>
<attribute name="Build-Date" value="${build.timestamp}" />
@ -67,6 +69,8 @@
<copy todir="${dist}/tmp/WEB-INF/classes">
<fileset dir="${build}"/>
</copy>
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<war basedir="${dist}/tmp" webxml="web.xml" destfile="${dist}/${war}">
<manifest>
<attribute name="Build-Date" value="${build.timestamp}" />
@ -81,9 +85,17 @@
<uptodate property="war.uptodate" targetfile="${dist}/${war}">
<srcfiles dir= "." includes="${build}/**/*.class, web.xml"/>
</uptodate>
<condition property="shouldListChanges" >
<and>
<not>
<isset property="war.uptodate" />
</not>
<isset property="mtn.available" />
</and>
</condition>
</target>
<target name="changes">
<target name="changes" depends="warUpToDate" if="shouldListChanges" >
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />

View File

@ -23,12 +23,14 @@ package net.i2p.addressbook;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import net.i2p.I2PAppContext;
import net.i2p.util.EepGet;
import net.i2p.util.SecureFile;
/**
* An address book for storing human readable names mapped to base64 i2p
@ -40,11 +42,12 @@ import net.i2p.util.EepGet;
*/
class AddressBook {
private String location;
private Map addresses;
private final String location;
/** either addresses or subFile will be non-null, but not both */
private final Map<String, String> addresses;
private final File subFile;
private boolean modified;
private static final boolean DEBUG = false;
/**
* Construct an AddressBook from the contents of the Map addresses.
@ -53,8 +56,10 @@ class AddressBook {
* A Map containing human readable addresses as keys, mapped to
* base64 i2p destinations.
*/
public AddressBook(Map addresses) {
public AddressBook(Map<String, String> addresses) {
this.addresses = addresses;
this.subFile = null;
this.location = null;
}
/*
@ -82,6 +87,7 @@ class AddressBook {
}
*/
static final long MAX_SUB_SIZE = 3 * 1024 * 1024l; //about 5,000 hosts
/**
* Construct an AddressBook from the Subscription subscription. If the
* address book at subscription has not changed since the last time it was
@ -90,33 +96,46 @@ class AddressBook {
*
* Yes, the EepGet fetch() is done in this constructor.
*
* This stores the subscription in a temporary file and does not read the whole thing into memory.
* An AddressBook created with this constructor may not be modified or written using write().
* It may be a merge source (an parameter for another AddressBook's merge())
* but may not be a merge target (this.merge() will throw an exception).
*
* @param subscription
* A Subscription instance pointing at a remote address book.
* @param proxyHost hostname of proxy
* @param proxyPort port number of proxy
*/
public AddressBook(Subscription subscription, String proxyHost, int proxyPort) {
File tmp = new File(I2PAppContext.getGlobalContext().getTempDir(), "addressbook.tmp");
Map<String, String> a = null;
File subf = null;
try {
File tmp = SecureFile.createTempFile("addressbook", null, I2PAppContext.getGlobalContext().getTempDir());
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
proxyHost, proxyPort, 0, -1l, MAX_SUB_SIZE, tmp.getAbsolutePath(), null,
subscription.getLocation(), true, subscription.getEtag(), subscription.getLastModified(), null);
if (get.fetch()) {
subscription.setEtag(get.getETag());
subscription.setLastModified(get.getLastModified());
subscription.setLastFetched(I2PAppContext.getGlobalContext().clock().now());
subf = tmp;
} else {
a = Collections.EMPTY_MAP;
tmp.delete();
}
} catch (IOException ioe) {
a = Collections.EMPTY_MAP;
}
this.addresses = a;
this.subFile = subf;
this.location = subscription.getLocation();
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
proxyHost, proxyPort, 0, -1l, MAX_SUB_SIZE, tmp.getAbsolutePath(), null,
subscription.getLocation(), true, subscription.getEtag(), subscription.getLastModified(), null);
if (get.fetch()) {
subscription.setEtag(get.getETag());
subscription.setLastModified(get.getLastModified());
subscription.setLastFetched(I2PAppContext.getGlobalContext().clock().now());
}
try {
this.addresses = ConfigParser.parse(tmp);
} catch (IOException exp) {
this.addresses = new HashMap();
}
tmp.delete();
}
/**
* Construct an AddressBook from the contents of the file at file. If the
* file cannot be read, construct an empty AddressBook
* file cannot be read, construct an empty AddressBook.
* This reads the entire file into memory.
* The resulting map is modifiable and may be a merge target.
*
* @param file
* A File pointing at a file with lines in the format
@ -125,22 +144,38 @@ class AddressBook {
*/
public AddressBook(File file) {
this.location = file.toString();
Map<String, String> a;
try {
this.addresses = ConfigParser.parse(file);
a = ConfigParser.parse(file);
} catch (IOException exp) {
this.addresses = new HashMap();
a = new HashMap();
}
this.addresses = a;
this.subFile = null;
}
/**
* Return a Map containing the addresses in the AddressBook.
*
* @return A Map containing the addresses in the AddressBook, where the key
* is a human readable name, and the value is a base64 i2p
* destination.
* Return an iterator over the addresses in the AddressBook.
* @since 0.8.7
*/
public Map getAddresses() {
return this.addresses;
public Iterator<Map.Entry<String, String>> iterator() {
if (this.subFile != null)
return new ConfigIterator(this.subFile);
return this.addresses.entrySet().iterator();
}
/**
* Delete the temp file or clear the map.
* @since 0.8.7
*/
public void delete() {
if (this.subFile != null) {
this.subFile.delete();
} else if (this.addresses != null) {
try {
this.addresses.clear();
} catch (UnsupportedOperationException uoe) {}
}
}
/**
@ -148,29 +183,32 @@ class AddressBook {
*
* @return A String representing either an abstract path, or a url,
* depending on how the instance was constructed.
* Will be null if created with the Map constructor.
*/
public String getLocation() {
return this.location;
}
/**
* Return a string representation of the contents of the AddressBook.
* Return a string representation of the origin of the AddressBook.
*
* @return A String representing the contents of the AddressBook.
* @return A String representing the origin of the AddressBook.
*/
@Override
public String toString() {
return this.addresses.toString();
if (this.location != null)
return "Book from " + this.location;
return "Map containing " + this.addresses.size() + " entries";
}
private static final int MIN_DEST_LENGTH = 516;
private static final int MAX_DEST_LENGTH = MIN_DEST_LENGTH + 100; // longer than any known cert type for now
/**
* Do basic validation of the hostname and dest
* Do basic validation of the hostname
* hostname was already converted to lower case by ConfigParser.parse()
*/
private static boolean valid(String host, String dest) {
public static boolean isValidKey(String host) {
return
host.endsWith(".i2p") &&
host.length() > 4 &&
@ -194,8 +232,15 @@ class AddressBook {
(! host.equals("console.i2p")) &&
(! host.endsWith(".proxy.i2p")) &&
(! host.endsWith(".router.i2p")) &&
(! host.endsWith(".console.i2p")) &&
(! host.endsWith(".console.i2p"))
;
}
/**
* Do basic validation of the b64 dest, without bothering to instantiate it
*/
private static boolean isValidDest(String dest) {
return
// 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)) &&
@ -216,18 +261,21 @@ class AddressBook {
* @param overwrite True to overwrite
* @param log
* The log to write messages about new addresses or conflicts to.
*
* @throws IllegalStateException if this was created with the Subscription constructor.
*/
public void merge(AddressBook other, boolean overwrite, Log log) {
Iterator otherIter = other.addresses.keySet().iterator();
if (this.addresses == null)
throw new IllegalStateException();
for (Iterator<Map.Entry<String, String>> iter = other.iterator(); iter.hasNext(); ) {
Map.Entry<String, String> entry = iter.next();
String otherKey = entry.getKey();
String otherValue = entry.getValue();
while (otherIter.hasNext()) {
String otherKey = (String) otherIter.next();
String otherValue = (String) other.addresses.get(otherKey);
if (valid(otherKey, otherValue)) {
if (isValidKey(otherKey) && isValidDest(otherValue)) {
if (this.addresses.containsKey(otherKey) && !overwrite) {
if (!this.addresses.get(otherKey).equals(otherValue)
&& log != null) {
if (DEBUG && log != null &&
!this.addresses.get(otherKey).equals(otherValue)) {
log.append("Conflict for " + otherKey + " from "
+ other.location
+ ". Destination in remote address book is "
@ -252,8 +300,12 @@ class AddressBook {
*
* @param file
* The file to write the contents of this AddressBook too.
*
* @throws IllegalStateException if this was created with the Subscription constructor.
*/
public void write(File file) {
if (this.addresses == null)
throw new IllegalStateException();
if (this.modified) {
try {
ConfigParser.write(this.addresses, file);
@ -267,8 +319,17 @@ class AddressBook {
* Write this AddressBook out to the file it was read from. Requires that
* AddressBook was constructed from a file on the local filesystem. If the
* file cannot be writen to, this method will silently fail.
*
* @throws IllegalStateException if this was not created with the File constructor.
*/
public void write() {
if (this.location == null || this.location.startsWith("http://"))
throw new IllegalStateException();
this.write(new File(this.location));
}
@Override
protected void finalize() {
delete();
}
}

View File

@ -0,0 +1,144 @@
/*
* 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.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* A class to iterate through a hosts.txt or config file without
* reading the whole thing into memory.
* Keys are always converted to lower case.
*
* Callers should iterate all the way through or call close()
* to ensure the underlying stream is closed.
*
* @since 0.8.7
*/
class ConfigIterator implements Iterator<Map.Entry<String, String>> {
private BufferedReader input;
private ConfigEntry next;
/**
* A dummy iterator in which hasNext() is always false.
*/
public ConfigIterator() {}
/**
* An iterator over the key/value pairs in the file.
*/
public ConfigIterator(File file) {
try {
FileInputStream fileStream = new FileInputStream(file);
input = new BufferedReader(new InputStreamReader(fileStream));
} catch (IOException ioe) {}
}
public boolean hasNext() {
if (input == null)
return false;
if (next != null)
return true;
try {
String inputLine = input.readLine();
while (inputLine != null) {
inputLine = ConfigParser.stripComments(inputLine);
String[] splitLine = inputLine.split("=");
if (splitLine.length == 2) {
next = new ConfigEntry(splitLine[0].trim().toLowerCase(), splitLine[1].trim());
return true;
}
inputLine = input.readLine();
}
} catch (IOException ioe) {}
try { input.close(); } catch (IOException ioe) {}
input = null;
next = null;
return false;
}
public Map.Entry<String, String> next() {
if (!hasNext())
throw new NoSuchElementException();
Map.Entry<String, String> rv = next;
next = null;
return rv;
}
public void remove() {
throw new UnsupportedOperationException();
}
public void close() {
if (input != null) {
try { input.close(); } catch (IOException ioe) {}
}
}
@Override
protected void finalize() {
close();
}
/**
* The object returned by the iterator.
*/
private static class ConfigEntry implements Map.Entry<String, String> {
private final String key;
private final String value;
public ConfigEntry(String k, String v) {
key = k;
value = v;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
public String setValue(String v) {
throw new UnsupportedOperationException();
}
public int hashCode() {
return key.hashCode() ^ value.hashCode();
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry) o;
return key.equals(e.getKey()) && value.equals(e.getValue());
}
}
}

View File

@ -30,7 +30,6 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -85,8 +84,8 @@ class ConfigParser {
* if the BufferedReader cannot be read.
*
*/
public static Map parse(BufferedReader input) throws IOException {
Map result = new HashMap();
public static Map<String, String> parse(BufferedReader input) throws IOException {
Map<String, String> result = new HashMap();
String inputLine;
inputLine = input.readLine();
while (inputLine != null) {
@ -111,11 +110,11 @@ class ConfigParser {
* @throws IOException
* if file cannot be read.
*/
public static Map parse(File file) throws IOException {
public static Map<String, String> parse(File file) throws IOException {
FileInputStream fileStream = new FileInputStream(file);
BufferedReader input = new BufferedReader(new InputStreamReader(
fileStream));
Map rv = ConfigParser.parse(input);
Map<String, String> rv = ConfigParser.parse(input);
try {
fileStream.close();
} catch (IOException ioe) {}
@ -132,7 +131,7 @@ class ConfigParser {
* @throws IOException
* if file cannot be read.
*/
public static Map parse(String string) throws IOException {
public static Map<String, String> parse(String string) throws IOException {
StringReader stringReader = new StringReader(string);
BufferedReader input = new BufferedReader(stringReader);
return ConfigParser.parse(input);
@ -149,14 +148,13 @@ class ConfigParser {
* @return A Map containing the key, value pairs from file, or if file
* cannot be read, map.
*/
public static Map parse(File file, Map map) {
Map result;
public static Map<String, String> parse(File file, Map<String, String> map) {
Map<String, String> result;
try {
result = ConfigParser.parse(file);
for (Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
String key = (String) iter.next();
if (!result.containsKey(key))
result.put(key, map.get(key));
for (Map.Entry<String, String> entry : map.entrySet()) {
if (!result.containsKey(entry.getKey()))
result.put(entry.getKey(), entry.getValue());
}
} catch (IOException exp) {
result = map;
@ -177,9 +175,9 @@ class ConfigParser {
* @throws IOException
* if input cannot be read.
*/
public static List parseSubscriptions(BufferedReader input)
public static List<String> parseSubscriptions(BufferedReader input)
throws IOException {
List result = new LinkedList();
List<String> result = new LinkedList();
String inputLine = input.readLine();
while (inputLine != null) {
inputLine = ConfigParser.stripComments(inputLine).trim();
@ -201,11 +199,11 @@ class ConfigParser {
* @throws IOException
* if file cannot be read.
*/
public static List parseSubscriptions(File file) throws IOException {
public static List<String> parseSubscriptions(File file) throws IOException {
FileInputStream fileStream = new FileInputStream(file);
BufferedReader input = new BufferedReader(new InputStreamReader(
fileStream));
List rv = ConfigParser.parseSubscriptions(input);
List<String> rv = ConfigParser.parseSubscriptions(input);
try {
fileStream.close();
} catch (IOException ioe) {}
@ -221,7 +219,7 @@ class ConfigParser {
* @throws IOException
* if string cannot be read.
*/
public static List parseSubscriptions(String string) throws IOException {
public static List<String> parseSubscriptions(String string) throws IOException {
StringReader stringReader = new StringReader(string);
BufferedReader input = new BufferedReader(stringReader);
return ConfigParser.parseSubscriptions(input);
@ -238,8 +236,8 @@ class ConfigParser {
* @return A List consisting of one element for each line in file, or if
* file cannot be read, list.
*/
public static List parseSubscriptions(File file, List list) {
List result;
public static List<String> parseSubscriptions(File file, List<String> list) {
List<String> result;
try {
result = ConfigParser.parseSubscriptions(file);
} catch (IOException exp) {
@ -263,12 +261,9 @@ class ConfigParser {
* @throws IOException
* if the BufferedWriter cannot be written to.
*/
public static void write(Map map, BufferedWriter output) throws IOException {
Iterator keyIter = map.keySet().iterator();
while (keyIter.hasNext()) {
String key = (String) keyIter.next();
output.write(key + "=" + (String) map.get(key));
public static void write(Map<String, String> map, BufferedWriter output) throws IOException {
for (Map.Entry<String, String> entry : map.entrySet()) {
output.write(entry.getKey() + '=' + entry.getValue());
output.newLine();
}
output.close();
@ -288,7 +283,7 @@ class ConfigParser {
* @throws IOException
* if file cannot be written to.
*/
public static void write(Map map, File file) throws IOException {
public static void write(Map<String, String> map, File file) throws IOException {
boolean success = false;
if (!isWindows) {
File tmp = SecureFile.createTempFile("temp-", ".tmp", file.getAbsoluteFile().getParentFile());
@ -318,12 +313,10 @@ class ConfigParser {
* @throws IOException
* if output cannot be written to.
*/
public static void writeSubscriptions(List list, BufferedWriter output)
public static void writeSubscriptions(List<String> list, BufferedWriter output)
throws IOException {
Iterator iter = list.iterator();
while (iter.hasNext()) {
output.write((String) iter.next());
for (String s : list) {
output.write(s);
output.newLine();
}
output.close();
@ -340,7 +333,7 @@ class ConfigParser {
* @throws IOException
* if output cannot be written to.
*/
public static void writeSubscriptions(List list, File file)
public static void writeSubscriptions(List<String> list, File file)
throws IOException {
ConfigParser.writeSubscriptions(list, new BufferedWriter(
new OutputStreamWriter(new SecureFileOutputStream(file), "UTF-8")));

View File

@ -22,13 +22,20 @@
package net.i2p.addressbook;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.client.naming.NamingService;
import net.i2p.client.naming.SingleFileNamingService;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.SecureDirectory;
/**
@ -41,6 +48,7 @@ public class Daemon {
public static final String VERSION = "2.0.4";
private static final Daemon _instance = new Daemon();
private boolean _running;
private static final boolean DEBUG = false;
/**
* Update the router and published address books using remote data from the
@ -49,29 +57,166 @@ public class Daemon {
* @param master
* The master AddressBook. This address book is never
* overwritten, so it is safe for the user to write to.
* It is only merged to the published addressbook.
* May be null.
* @param router
* The router AddressBook. This is the address book read by
* client applications.
* @param published
* The published AddressBook. This address book is published on
* the user's eepsite so that others may subscribe to it.
* May be null.
* If non-null, overwrite with the new addressbook.
* @param subscriptions
* A SubscriptionList listing the remote address books to update
* from.
* @param log
* The log to write changes and conflicts to.
* May be null.
*/
public void update(AddressBook master, AddressBook router,
public static void update(AddressBook master, AddressBook router,
File published, SubscriptionList subscriptions, Log log) {
router.merge(master, true, null);
Iterator iter = subscriptions.iterator();
Iterator<AddressBook> iter = subscriptions.iterator();
while (iter.hasNext()) {
// yes, the EepGet fetch() is done in next()
router.merge((AddressBook) iter.next(), false, log);
router.merge(iter.next(), false, log);
}
router.write();
if (published != null)
if (published != null) {
if (master != null)
router.merge(master, true, null);
router.write(published);
}
subscriptions.write();
}
/**
* Update the router and published address books using remote data from the
* subscribed address books listed in subscriptions.
* Merging of the "master" addressbook is NOT supported.
*
* @param router
* The NamingService to update, generally the root NamingService from the context.
* @param published
* The published AddressBook. This address book is published on
* the user's eepsite so that others may subscribe to it.
* May be null.
* If non-null, overwrite with the new addressbook.
* @param subscriptions
* A SubscriptionList listing the remote address books to update
* from.
* @param log
* The log to write changes and conflicts to.
* May be null.
* @since 0.8.7
*/
public static void update(NamingService router, File published, SubscriptionList subscriptions, Log log) {
// If the NamingService is a database, we look up as we go.
// If it is a text file, we do things differently, to avoid O(n**2) behavior
// when scanning large subscription results (i.e. those that return the whole file, not just the new entries) -
// we load all the known hostnames into a Set one time.
// This also has the advantage of not flushing the NamingService's LRU cache.
String nsClass = router.getClass().getSimpleName();
boolean isTextFile = nsClass.equals("HostsTxtNamingService") || nsClass.equals("SingleFileNamingService");
Set<String> knownNames = null;
NamingService publishedNS = null;
Iterator<AddressBook> iter = subscriptions.iterator();
while (iter.hasNext()) {
// yes, the EepGet fetch() is done in next()
long start = System.currentTimeMillis();
AddressBook sub = iter.next();
long end = System.currentTimeMillis();
// SubscriptionIterator puts in a dummy AddressBook with no location if no fetch is done
if (DEBUG && log != null && sub.getLocation() != null)
log.append("Fetch of " + sub.getLocation() + " took " + (end - start));
start = end;
int old = 0, nnew = 0, invalid = 0, conflict = 0, total = 0;
for (Iterator<Map.Entry<String, String>> eIter = sub.iterator(); eIter.hasNext(); ) {
Map.Entry<String, String> entry = eIter.next();
String key = entry.getKey();
boolean isKnown;
Destination oldDest = null;
if (isTextFile) {
if (knownNames == null) {
// load the hostname set
Properties opts = new Properties();
opts.setProperty("file", "hosts.txt");
knownNames = router.getNames(opts);
}
isKnown = knownNames.contains(key);
} else {
oldDest = router.lookup(key);
isKnown = oldDest != null;
}
try {
if (!isKnown) {
if (AddressBook.isValidKey(key)) {
Destination dest = new Destination(entry.getValue());
Properties props = new Properties();
props.setProperty("s", sub.getLocation());
boolean success = router.put(key, dest, props);
if (log != null) {
if (success)
log.append("New address " + key +
" added to address book. From: " + sub.getLocation());
else
log.append("Save to naming service " + router + " failed for new key " + key);
}
// now update the published addressbook
if (published != null) {
if (publishedNS == null)
publishedNS = new SingleFileNamingService(I2PAppContext.getGlobalContext(), published.getAbsolutePath());
success = publishedNS.putIfAbsent(key, dest);
if (!success) {
try {
log.append("Save to published address book " + published.getCanonicalPath() + " failed for new key " + key);
} catch (IOException ioe) {}
}
}
if (isTextFile)
// keep track for later dup check
knownNames.add(key);
nnew++;
} else if (log != null) {
log.append("Bad hostname " + key + " from "
+ sub.getLocation());
invalid++;
}
} else if (false && DEBUG && log != null) {
// lookup the conflict if we haven't yet (O(n**2) for text file)
if (isTextFile)
oldDest = router.lookup(key);
if (oldDest != null && !oldDest.toBase64().equals(entry.getValue())) {
log.append("Conflict for " + key + " from "
+ sub.getLocation()
+ ". Destination in remote address book is "
+ entry.getValue());
conflict++;
} else {
old++;
}
} else {
old++;
}
} catch (DataFormatException dfe) {
if (log != null)
log.append("Invalid b64 for " + key + " From: " + sub.getLocation());
invalid++;
}
total++;
}
if (DEBUG && log != null && total > 0) {
log.append("Merge of " + sub.getLocation() + " into " + router +
" took " + (System.currentTimeMillis() - start) + " ms with " +
total + " total, " +
nnew + " new, " +
old + " old, " +
invalid + " invalid, " +
conflict + " conflicts");
}
sub.delete();
}
subscriptions.write();
}
@ -83,44 +228,80 @@ public class Daemon {
* @param home
* The directory containing addressbook's configuration files.
*/
public void update(Map settings, String home) {
File masterFile = new File(home, (String) settings
.get("master_addressbook"));
File routerFile = new File(home, (String) settings
.get("router_addressbook"));
public static void update(Map<String, String> settings, String home) {
File published = null;
if ("true".equals(settings.get("should_publish")))
published = new File(home, (String) settings
boolean should_publish = Boolean.valueOf(settings.get("should_publish")).booleanValue();
if (should_publish)
published = new File(home, settings
.get("published_addressbook"));
File subscriptionFile = new File(home, (String) settings
File subscriptionFile = new File(home, settings
.get("subscriptions"));
File logFile = new File(home, (String) settings.get("log"));
File etagsFile = new File(home, (String) settings.get("etags"));
File lastModifiedFile = new File(home, (String) settings
File logFile = new File(home, settings.get("log"));
File etagsFile = new File(home, settings.get("etags"));
File lastModifiedFile = new File(home, settings
.get("last_modified"));
File lastFetchedFile = new File(home, (String) settings
File lastFetchedFile = new File(home, settings
.get("last_fetched"));
long delay;
try {
delay = Long.parseLong((String) settings.get("update_delay"));
delay = Long.parseLong(settings.get("update_delay"));
} catch (NumberFormatException nfe) {
delay = 12;
}
delay *= 60 * 60 * 1000;
AddressBook master = new AddressBook(masterFile);
AddressBook router = new AddressBook(routerFile);
List defaultSubs = new LinkedList();
List<String> defaultSubs = new LinkedList();
// defaultSubs.add("http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/i2p/hosts.txt");
defaultSubs.add("http://www.i2p2.i2p/hosts.txt");
SubscriptionList subscriptions = new SubscriptionList(subscriptionFile,
etagsFile, lastModifiedFile, lastFetchedFile, delay, defaultSubs, (String) settings
.get("proxy_host"), Integer.parseInt((String) settings.get("proxy_port")));
etagsFile, lastModifiedFile, lastFetchedFile, delay, defaultSubs, settings
.get("proxy_host"), Integer.parseInt(settings.get("proxy_port")));
Log log = new Log(logFile);
update(master, router, published, subscriptions, log);
// If false, add hosts via naming service; if true, write hosts.txt file directly
// Default false
if (Boolean.valueOf(settings.get("update_direct")).booleanValue()) {
// Direct hosts.txt access
File routerFile = new File(home, settings.get("router_addressbook"));
AddressBook master;
if (should_publish) {
File masterFile = new File(home, settings.get("master_addressbook"));
master = new AddressBook(masterFile);
} else {
master = null;
}
AddressBook router = new AddressBook(routerFile);
update(master, router, published, subscriptions, log);
} else {
// Naming service - no merging of master to router and published is supported.
update(getNamingService(settings.get("naming_service")), published, subscriptions, log);
}
}
/** depth-first search */
private static NamingService searchNamingService(NamingService ns, String srch)
{
String name = ns.getName();
if (name.equals(srch) || name.endsWith('/' + srch) || name.endsWith('\\' + srch))
return ns;
List<NamingService> list = ns.getNamingServices();
if (list != null) {
for (NamingService nss : list) {
NamingService rv = searchNamingService(nss, srch);
if (rv != null)
return rv;
}
}
return null;
}
/** @return the configured NamingService, or the root NamingService */
private static NamingService getNamingService(String srch)
{
NamingService root = I2PAppContext.getGlobalContext().namingService();
NamingService rv = searchNamingService(root, srch);
return rv != null ? rv : root;
}
/**
@ -149,7 +330,7 @@ public class Daemon {
homeFile = new SecureDirectory(System.getProperty("user.dir"));
}
Map defaultSettings = new HashMap();
Map<String, String> defaultSettings = new HashMap();
defaultSettings.put("proxy_host", "127.0.0.1");
defaultSettings.put("proxy_port", "4444");
defaultSettings.put("master_addressbook", "../userhosts.txt");
@ -162,6 +343,8 @@ public class Daemon {
defaultSettings.put("last_modified", "last_modified");
defaultSettings.put("last_fetched", "last_fetched");
defaultSettings.put("update_delay", "12");
defaultSettings.put("update_direct", "false");
defaultSettings.put("naming_service", "hosts.txt");
if (!homeFile.exists()) {
boolean created = homeFile.mkdirs();
@ -173,7 +356,7 @@ public class Daemon {
File settingsFile = new File(homeFile, settingsLocation);
Map settings = ConfigParser.parse(settingsFile, defaultSettings);
Map<String, String> settings = ConfigParser.parse(settingsFile, defaultSettings);
// wait
try {
Thread.sleep(5*60*1000 + I2PAppContext.getGlobalContext().random().nextLong(5*60*1000));
@ -181,7 +364,7 @@ public class Daemon {
} catch (InterruptedException ie) {}
while (_running) {
long delay = Long.parseLong((String) settings.get("update_delay"));
long delay = Long.parseLong(settings.get("update_delay"));
if (delay < 1) {
delay = 1;
}

View File

@ -21,13 +21,18 @@
package net.i2p.addressbook;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.client.naming.NamingServiceUpdater;
/**
* A thread that waits five minutes, then runs the addressbook daemon.
*
* @author Ragnarok
*
*/
class DaemonThread extends Thread {
public class DaemonThread extends Thread implements NamingServiceUpdater {
private String[] args;
@ -49,11 +54,22 @@ class DaemonThread extends Thread {
// Thread.sleep(5 * 60 * 1000);
//} catch (InterruptedException exp) {
//}
I2PAppContext.getGlobalContext().namingService().registerUpdater(this);
Daemon.main(this.args);
I2PAppContext.getGlobalContext().namingService().unregisterUpdater(this);
}
public void halt() {
Daemon.stop();
interrupt();
}
/**
* The NamingServiceUpdater interface
* @param options ignored
* @since 0.8.7
*/
public void update(Properties options) {
interrupt();
}
}

View File

@ -35,9 +35,9 @@ import net.i2p.data.DataHelper; // debug
*
* @author Ragnarok
*/
class SubscriptionIterator implements Iterator {
class SubscriptionIterator implements Iterator<AddressBook> {
private Iterator subIterator;
private Iterator<Subscription> subIterator;
private String proxyHost;
private int proxyPort;
private final long delay;
@ -51,7 +51,7 @@ class SubscriptionIterator implements Iterator {
* @param proxyHost proxy hostname
* @param proxyPort proxt port number
*/
public SubscriptionIterator(List subscriptions, long delay, String proxyHost, int proxyPort) {
public SubscriptionIterator(List<Subscription> subscriptions, long delay, String proxyHost, int proxyPort) {
this.subIterator = subscriptions.iterator();
this.delay = delay;
this.proxyHost = proxyHost;
@ -72,8 +72,8 @@ class SubscriptionIterator implements Iterator {
* see java.util.Iterator#next()
* @return an AddressBook (empty if the minimum delay has not been met)
*/
public Object next() {
Subscription sub = (Subscription) this.subIterator.next();
public AddressBook next() {
Subscription sub = this.subIterator.next();
if (sub.getLastFetched() + this.delay < I2PAppContext.getGlobalContext().clock().now()) {
//System.err.println("Fetching addressbook from " + sub.getLocation());
return new AddressBook(sub, this.proxyHost, this.proxyPort);

View File

@ -24,7 +24,6 @@ package net.i2p.addressbook;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -37,7 +36,7 @@ import java.util.Map;
*/
class SubscriptionList {
private List subscriptions;
private List<Subscription> subscriptions;
private File etagsFile;
@ -68,7 +67,7 @@ class SubscriptionList {
* @param proxyPort proxy port number
*/
public SubscriptionList(File locationsFile, File etagsFile,
File lastModifiedFile, File lastFetchedFile, long delay, List defaultSubs, String proxyHost,
File lastModifiedFile, File lastFetchedFile, long delay, List<String> defaultSubs, String proxyHost,
int proxyPort) {
this.subscriptions = new LinkedList();
this.etagsFile = etagsFile;
@ -77,11 +76,10 @@ class SubscriptionList {
this.delay = delay;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
Map etags;
Map lastModified;
Map lastFetched;
String location;
List locations = ConfigParser.parseSubscriptions(locationsFile,
Map<String, String> etags;
Map<String, String> lastModified;
Map<String, String> lastFetched;
List<String> locations = ConfigParser.parseSubscriptions(locationsFile,
defaultSubs);
try {
etags = ConfigParser.parse(etagsFile);
@ -98,12 +96,10 @@ class SubscriptionList {
} catch (IOException exp) {
lastFetched = new HashMap();
}
Iterator iter = locations.iterator();
while (iter.hasNext()) {
location = (String) iter.next();
this.subscriptions.add(new Subscription(location, (String) etags.get(location),
(String) lastModified.get(location),
(String) lastFetched.get(location)));
for (String location : locations) {
this.subscriptions.add(new Subscription(location, etags.get(location),
lastModified.get(location),
lastFetched.get(location)));
}
}
@ -125,13 +121,10 @@ class SubscriptionList {
* won't be read back correctly; the '=' should be escaped.
*/
public void write() {
Iterator iter = this.subscriptions.iterator();
Subscription sub;
Map etags = new HashMap();
Map lastModified = new HashMap();
Map lastFetched = new HashMap();
while (iter.hasNext()) {
sub = (Subscription) iter.next();
Map<String, String> etags = new HashMap();
Map<String, String> lastModified = new HashMap();
Map<String, String> lastFetched = new HashMap();
for (Subscription sub : this.subscriptions) {
if (sub.getEtag() != null) {
etags.put(sub.getLocation(), sub.getEtag());
}

View File

@ -1,381 +0,0 @@
package net.i2p.client;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.Clock;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* ATalk - anonymous talk, demonstrating a trivial I2P usage scenario.
* Run this class with no arguments for a manual.
*
* @author jrandom
*/
public class ATalk implements I2PSessionListener, Runnable {
/** logging hook - status messages are piped to this */
private final static Log _log = new Log(ATalk.class);
/** platform independent newline */
private final static String NL = System.getProperty("line.separator");
/** the current session */
private I2PSession _session;
/** who am i */
private Destination _myDestination;
/** who are you? */
private Destination _peerDestination;
/** location of my secret key file */
private String _myKeyFile;
/** location of their public key */
private String _theirDestinationFile;
/** where the application reads input from. currently set to standard input */
private BufferedReader _in;
/** where the application sends output to. currently set to standard output */
private BufferedWriter _out;
/** string that messages must begin with to be treated as files */
private final static String FILE_COMMAND = ".file: ";
/** the, erm, manual */
private final static String MANUAL = "ATalk: Anonymous Talk, a demo program for the Invisible Internet Project SDK"
+ NL
+ "To generate a new destination:"
+ NL
+ "\tATalk [fileToSavePrivateKeyIn] [fileToSavePublicKeyIn]"
+ NL
+ "To talk to another destination:"
+ NL
+ "\tATalk [myPrivateKeyFile] [peerPublicKey] [shouldLogToScreen]"
+ NL
+ "shouldLogToScreen is 'true' or 'false', depending on whether you want log info on the screen"
+ NL
+ "When talking to another destination, messages are sent after you hit return"
+ NL
+ "To send a file, send a message saying:"
+ NL
+ "\t"
+ FILE_COMMAND
+ "[filenameToSend]"
+ NL
+ "The peer will then recieve the file and be notified of where it has been saved"
+ NL
+ "To end the talk session, enter a period on a line by itself and hit return"
+ NL;
public final static String PROP_CONFIG_LOCATION = "configFile";
private static final SimpleDateFormat _fmt = new SimpleDateFormat("hh:mm:ss.SSS");
/** Construct the talk engine, but don't connect yet */
public ATalk(String myKeyFile, String theirDestFile) {
_myKeyFile = myKeyFile;
_theirDestinationFile = theirDestFile;
}
/** Actually start up the connection to the I2P network.
* Successful connect does not mean the peer is online or reachable.
*
* @throws IOException if there is a problem reading in the keys from the files specified
* @throws DataFormatException if the key files are not in the valid format
* @throws I2PSessionException if there is a problem contacting the I2P router
*/
public void connect() throws IOException, I2PSessionException, DataFormatException {
I2PClient client = I2PClientFactory.createClient();
File myFile = new File(_myKeyFile);
Properties props = new Properties();
String configLocation = System.getProperty(PROP_CONFIG_LOCATION, "atalk.config");
try {
props.load(new FileInputStream(configLocation));
} catch (FileNotFoundException fnfe) {
_log.warn("Unable to load up the ATalk config file " + configLocation);
}
// Provide any router or client API configuration here.
if (!props.containsKey(I2PClient.PROP_TCP_HOST))
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
if (!props.containsKey(I2PClient.PROP_TCP_PORT))
props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
if (!props.containsKey(I2PClient.PROP_RELIABILITY))
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT);
_session = client.createSession(new FileInputStream(myFile), props);
_session.setSessionListener(this);
_session.connect();
File peerDestFile = new File(_theirDestinationFile);
_peerDestination = new Destination();
_peerDestination.readBytes(new FileInputStream(peerDestFile));
return;
}
/** Actual bulk processing of the application, reading in user input,
* sending messages, and displaying results. When this function exits, the
* application is complete.
*
*/
public void run() {
try {
connect();
_in = new BufferedReader(new InputStreamReader(System.in));
_out = new BufferedWriter(new OutputStreamWriter(System.out));
_out.write("Starting up anonymous talk session" + NL);
while (true) {
String line = _in.readLine();
if ((line == null) || (line.trim().length() <= 0)) continue;
if (".".equals(line)) {
boolean ok = _session.sendMessage(_peerDestination, ("Peer disconnected at " + now()).getBytes());
// ignore ok, we're closing
break;
}
if (line.startsWith(FILE_COMMAND) && (line.trim().length() > FILE_COMMAND.length())) {
try {
String file = line.substring(FILE_COMMAND.length());
boolean sent = sendFile(file);
if (!sent) {
_out.write("Failed sending the file: " + file + NL);
}
} catch (IOException ioe) {
_out.write("Error sending the file: " + ioe.getMessage() + NL);
_log.error("Error sending the file", ioe);
}
} else {
boolean ok = _session.sendMessage(_peerDestination, ("[" + now() + "] " + line).getBytes());
if (!ok) {
_out.write("Failed sending message. Peer disconnected?" + NL);
}
}
}
} catch (IOException ioe) {
_log.error("Error running", ioe);
} catch (I2PSessionException ise) {
_log.error("Error communicating", ise);
} catch (DataFormatException dfe) {
_log.error("Peer destination file is not valid", dfe);
} finally {
try {
_log.debug("Exiting anonymous talk session");
if (_out != null) _out.write("Exiting anonymous talk session");
} catch (IOException ioe) {
// ignored
}
if (_session != null) {
try {
_session.destroySession();
} catch (I2PSessionException ise) {
// ignored
}
}
try {
Thread.sleep(5000);
} catch (InterruptedException ie) { // nop!
}
}
}
private String now() {
Date now = new Date(Clock.getInstance().now());
return _fmt.format(now);
}
/** Send the given file to the current peer. This works by sending a message
* saying ".file: filename\nbodyOfFile", where filename is the name of the file
* (which the recipient will be shown), and the bodyOfFile is the set of raw
* bytes in the file.
*
* @throws IOException if the file could not be found or read
* @return false if the file could not be sent to the peer
*/
private boolean sendFile(String filename) throws IOException, I2PSessionException {
_log.debug("Sending file [" + filename + "]");
ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
baos.write((FILE_COMMAND + filename + "\n").getBytes());
FileInputStream fin = new FileInputStream(filename);
byte buf[] = new byte[4096];
try {
while (true) {
int len = fin.read(buf);
if (len == -1) break;
baos.write(buf, 0, len);
}
} catch (IOException ioe) {
_log.debug("Failed reading the file", ioe);
return false;
}
baos.close();
byte val[] = baos.toByteArray();
_log.debug("Sending " + filename + " with a full payload of " + val.length);
try {
boolean rv = _session.sendMessage(_peerDestination, val);
_log.debug("Sending " + filename + " complete: rv = " + rv);
return rv;
} catch (Throwable t) {
_log.error("Error sending file", t);
return false;
}
}
/** I2PSessionListener.messageAvailable requires this method to be called whenever
* I2P wants to tell the session that a message is available. ATalk always grabs
* the message immediately and either processes it as a "send file" command (passing
* it off to handleRecieveFile(..) or simply displays the
* message to the user.
*
*/
public void messageAvailable(I2PSession session, int msgId, long size) {
_log.debug("Message available: id = " + msgId + " size = " + size);
try {
byte msg[] = session.receiveMessage(msgId);
// inefficient way to just read the first line of text, but its easy
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(msg)));
String line = reader.readLine();
if (line.startsWith(FILE_COMMAND)) {
handleRecieveFile(line, msg);
} else {
// not a file command, so just plop 'er out on the screen
_out.write(now() + " --> " + new String(msg));
_out.write(NL);
_out.flush();
}
} catch (I2PSessionException ise) {
_log.error("Error fetching available message", ise);
} catch (IOException ioe) {
_log.error("Error writing out the message", ioe);
}
}
/** React to a file being sent our way from the peer via {@link #sendFile sendFile}
* by saving the file to a temporary location and displaying where, what, and how large
* it is.
*
* @param firstline the first line of the message that, according to the sendFile
* implementation, contains the command and the filename that it was stored
* at on the peer's computer
* @param msg the entire message recieved, including the firstline
*/
private void handleRecieveFile(String firstline, byte msg[]) throws IOException {
_log.debug("handleRecieveFile called");
File f = File.createTempFile("recieve", ".dat", new File("."));
FileOutputStream fos = new FileOutputStream(f);
int lineLen = firstline.getBytes().length + "\n".getBytes().length;
int lenToCopy = msg.length - lineLen;
byte buf[] = new byte[lenToCopy];
System.arraycopy(msg, lineLen, buf, 0, lenToCopy);
fos.write(buf);
fos.close();
String name = firstline.substring(FILE_COMMAND.length());
_out.write("Recieved a file called [" + name + "] of size [" + lenToCopy + "] bytes, saved as ["
+ f.getAbsolutePath() + "]" + NL);
_out.flush();
}
/** driver */
public static void main(String args[]) {
I2PAppContext context = new I2PAppContext();
if (args.length == 2) {
String myKeyFile = args[0];
String myDestinationFile = args[1];
boolean success = generateKeys(myKeyFile, myDestinationFile);
if (success)
_log.debug("Keys generated (private key file: " + myKeyFile + " destination file: " + myDestinationFile
+ ")");
else
_log.debug("Keys generation failed");
try {
Thread.sleep(5000);
} catch (InterruptedException ie) { // nop
}
} else if (args.length == 3) {
_log.debug("Starting chat");
String myKeyfile = args[0];
String peerDestFile = args[1];
String shouldLog = args[2];
if (Boolean.TRUE.toString().equalsIgnoreCase(shouldLog))
context.logManager().setDisplayOnScreen(true);
else
context.logManager().setDisplayOnScreen(false);
String logFile = args[2];
Thread talkThread = new I2PThread(new ATalk(myKeyfile, peerDestFile));
talkThread.start();
} else {
System.out.println(MANUAL);
try {
Thread.sleep(5000);
} catch (InterruptedException ie) { // nop
}
System.exit(-1);
}
}
/** Generate a new Destination, saving that destination and the associated
* private keys in the privKeyFile, and also saving the destination without
* any private keys to destinationFile.
*
* @param privKeyFile private key file, including the destination and the various
* private keys, as defined by {@link I2PClient#createDestination I2PClient.createDestination}
* @param destinationFile file in which the Destination is serialized in
*/
private static boolean generateKeys(String privKeyFile, String destinationFile) {
try {
Destination d = I2PClientFactory.createClient().createDestination(new FileOutputStream(privKeyFile));
FileOutputStream fos = new FileOutputStream(destinationFile);
d.writeBytes(fos);
fos.flush();
fos.close();
return true;
} catch (IOException ioe) {
_log.error("Error generating keys", ioe);
} catch (I2PException ipe) {
_log.error("Error generating keys", ipe);
}
return false;
}
/** required by {@link I2PSessionListener I2PSessionListener} to notify of disconnect */
public void disconnected(I2PSession session) {
_log.debug("Disconnected");
}
/** required by {@link I2PSessionListener I2PSessionListener} to notify of error */
public void errorOccurred(I2PSession session, String message, Throwable error) {
_log.debug("Error occurred: " + message, error);
}
/** required by {@link I2PSessionListener I2PSessionListener} to notify of abuse */
public void reportAbuse(I2PSession session, int severity) {
_log.debug("Abuse reported of severity " + severity);
}
}

View File

@ -9,6 +9,7 @@
<property name="javadoc" value="javadoc"/>
<property name="javac.compilerargs" value=""/>
<property name="require.gettext" value="true" />
<target name="init">
<mkdir dir="${build}"/>
@ -29,8 +30,7 @@
<compilerarg line="${javac.compilerargs}" />
<classpath>
<pathelement location="../../core/java/build/i2p.jar" />
<!-- doesn't matter if we're not on win32, we just need the java classes, not the platform-dependent code -->
<pathelement location="../../installer/lib/wrapper/win32/wrapper.jar" />
<pathelement location="../../installer/lib/wrapper/all/wrapper.jar" />
<pathelement location="../../router/java/build/router.jar" />
</classpath>
</javac>
@ -39,17 +39,20 @@
</copy>
</target>
<target name="jar" depends="compile">
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<target name="bundle" >
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >
<arg value="./bundle-messages.sh" />
</exec>
<!-- multi-lang is optional -->
<exec executable="sh" osfamily="windows" failifexecutionfails="false" >
<arg value="./bundle-messages.sh" />
</exec>
</target>
<target name="listChangedFiles" depends="jarUpToDate" if="shouldListChanges" >
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
@ -61,6 +64,11 @@
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<target name="jar" depends="compile, bundle, listChangedFiles" unless="jar.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar basedir="${build}" destfile="${dist}/${jar}">
<manifest>
<attribute name="Main-Class" value="net.i2p.desktopgui.Main"/>
@ -71,6 +79,20 @@
</jar>
</target>
<target name="jarUpToDate">
<uptodate property="jar.uptodate" targetfile="${dist}/${jar}" >
<srcfiles dir= "." includes="build/**/*.class" />
</uptodate>
<condition property="shouldListChanges" >
<and>
<not>
<isset property="jar.uptodate" />
</not>
<isset property="mtn.available" />
</and>
</condition>
</target>
<target name="javadoc">
<mkdir dir="${build}" />
<mkdir dir="${build}/${javadoc}" />
@ -88,15 +110,15 @@
</target>
<target name="poupdate">
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="windows" failifexecutionfails="true" >
<exec executable="sh" osfamily="windows" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>

View File

@ -13,6 +13,7 @@
CLASS=net.i2p.desktopgui.messages
TMPFILE=build/javafiles.txt
export TZ=UTC
RC=0
if [ "$1" = "-p" ]
then
@ -76,15 +77,17 @@ do
-o ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - xgettext failed, not updating translations'
echo "ERROR - xgettext failed on ${i}, not updating translations"
rm -f ${i}t
RC=1
break
fi
msgmerge -U --backup=none $i ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - msgmerge failed, not updating translations'
echo "ERROR - msgmerge failed on ${i}, not updating translations"
rm -f ${i}t
RC=1
break
fi
rm -f ${i}t
@ -101,11 +104,13 @@ do
msgfmt --java --statistics -r $CLASS -l $LG -d build $i
if [ $? -ne 0 ]
then
echo 'Warning - msgfmt failed, not updating translations'
echo "ERROR - msgfmt failed on ${i}, not updating translations"
# msgfmt leaves the class file there so the build would work the next time
find build -name messages_${LG}.class -exec rm -f {} \;
RC=1
break
fi
fi
done
rm -f $TMPFILE
# todo: return failure
exit 0
exit $RC

View File

@ -0,0 +1,55 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P desktopgui\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-20 11:53+0000\n"
"PO-Revision-Date: 2011-02-26 19:46-0000\n"
"Last-Translator: hamada <hamada@mail.i2p>\n"
"Language-Team: duck <duck@mail.i2p>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "ابدأ I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "جاري تشغيل I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "جاري البدأ"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr " تشغيل متصفح I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "اعدادات"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "اعادة تشغيل"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "توقيف I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "اعدادات الأيقونة"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "هل ترغب في تفعيل الأيقونة؟"

View File

@ -0,0 +1,57 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# <kia___@hushmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-07-12 19:41+0000\n"
"Last-Translator: KIA <kia___@hushmail.com>\n"
"Language-Team: Danish (http://www.transifex.net/projects/p/I2P/team/da/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: da\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Start I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P starter nu!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Starter"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Start I2P Browseren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Konfigurer desktopgui"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Genstart I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Stop I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Konfiguration af processbar ikonet"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "Skal processbar ikonet være aktivt?"

View File

@ -0,0 +1,55 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-03-22 15:49+0000\n"
"Last-Translator: blabla <blabla@trash-mail.com>\n"
"Language-Team: German <>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "I2P starten"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P startet gerade!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Startend"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "I2P-Browser öffnen"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Desktopgui konfigurieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "I2P neustarten"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "I2P beenden"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Systemleistensymbol konfigurieren"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "Systemleistensymbol aktivieren?"

View File

@ -8,10 +8,11 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P desktopgui\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-20 11:53+0000\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2010-06-15 14:09+0100\n"
"Last-Translator: duck <duck@mail.i2p>\n"
"Language-Team: duck <duck@mail.i2p>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@ -0,0 +1,56 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-04-02 23:57+0100\n"
"Last-Translator: mixxy <m1xxy@mail.i2p>\n"
"Language-Team: Spanish (Castilian) <None>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Iniciar I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P está iniciando!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Iniciando"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Lanzar navegador I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Configurar desktopgui"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Reiniciar I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Detener I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Configuración del ícono de la barra de tareas"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "¿Debería estar activado el ícono de la barra de tareas?"

View File

@ -0,0 +1,56 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
# foo <foo@bar>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: I2P desktopgui\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-03-30 21:58+0100\n"
"Last-Translator: magma <magma@mail.i2p>\n"
"Language-Team: duck <duck@mail.i2p>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Démarrer I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P démarre!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Démarrage"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Lancer le navigateur"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Configurer l'interface de bureau"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Redémarrer I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Arrêter I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Configuration de l'icône de notification"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "Activer l'icône de notification"

View File

@ -0,0 +1,57 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# <jokjok@hotmail.it>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-06-09 17:09+0000\n"
"Last-Translator: mkkid <jokjok@hotmail.it>\n"
"Language-Team: Italian (http://www.transifex.net/projects/p/I2P/team/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Avvia I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "Avvio di I2P in corso!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Avvio"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Avvia il Browser I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Configura desktopgui"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Riavvia I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Ferma I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Configurazione dell'icona nell'Area di notifica"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "Vuoi che l'icona nell'Area di notifica venga abilitata?"

View File

@ -0,0 +1,57 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# <b790979@klzlk.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-05-25 18:36+0000\n"
"Last-Translator: PolishAnon <b790979@klzlk.com>\n"
"Language-Team: Polish (http://www.transifex.net/projects/p/I2P/team/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pl\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Uruchom I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "Uruchamianie I2P!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Uruchamianie"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Uruchom Przeglądarke I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Skonfiguruj intrefejs pulpitu (desktopgui)"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Zrestartuj I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Zatrzymaj I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Konfiguracja ikony zasobnika"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "Czy ikona zasobnika powinna być aktywna?"

View File

@ -0,0 +1,57 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# 123hund123 <M8R-ra4r1r@mailinator.com>, 2011
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-03-22 15:49+0000\n"
"Last-Translator: 123hund123 <M8R-ra4r1r@mailinator.com>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.net/projects/p/I2P/team/sv_SE/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: sv_SE\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Starta I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P startas!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Startar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Öppna I2P browser"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Konfigurera desktopgui"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Starta om I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Stoppar I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Ikonpanelskonfiguration"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "Ska ikonpanelen vara aktiverad?"

View File

@ -0,0 +1,57 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# <gribua@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-06-19 14:01+0000\n"
"Last-Translator: Pharmasolin <gribua@gmail.com>\n"
"Language-Team: Ukrainian (Ukraine) (http://www.transifex.net/projects/p/I2P/team/uk_UA/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: uk_UA\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Запустити I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P запускається!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Запускається"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Запустити I2P Браузер"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Настроїти вигляд інтерфейсу"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Перезапустити I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Зупинити I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Настройка трей-іконки"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "Чм повинна трей-іконка бути включена?"

View File

@ -0,0 +1,57 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# dich_tran <tran.nathan@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-04-12 06:13+0000\n"
"Last-Translator: dich_tran <tran.nathan@gmail.com>\n"
"Language-Team: Vietnamese (http://www.transifex.net/projects/p/I2P/team/vi/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: vi\n"
"Plural-Forms: nplurals=1; plural=0\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
msgstr "Khởi động I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "I2P is starting!"
msgstr "I2P đang bắt đầu"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:38
msgid "Starting"
msgstr "Bắt đầu"
#: src/net/i2p/desktopgui/InternalTrayManager.java:26
msgid "Launch I2P Browser"
msgstr "Kích hoạt trình duyệt I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "Cấu hình giao diện"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
msgstr "Khởi động lại I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:85
msgid "Stop I2P"
msgstr "Ngưng I2P"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "Cấu hình tray icon"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "Cần dùng tray icon?"

View File

@ -1,14 +1,23 @@
# I2P
# Copyright (C) 2009 The I2P Project
# This file is distributed under the same license as the desktopgui package.
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# ducki2p <ducki2p@gmail.com>, 2011.
# walking <walking@i2pmail.org>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-16 17:10+0000\n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-03-03 18:29+0000\n"
"PO-Revision-Date: 2011-03-24 09:18+0000\n"
"Last-Translator: walking <walking@i2pmail.org>\n"
"Language-Team: Chinese (China) (http://www.transifex.net/projects/p/I2P/team/zh_CN/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"Plural-Forms: nplurals=1; plural=0\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:23
msgid "Start I2P"
@ -28,7 +37,7 @@ msgstr "正在启动I2P浏览器"
#: src/net/i2p/desktopgui/InternalTrayManager.java:50
msgid "Configure desktopgui"
msgstr "界面设置"
msgstr "设置desktopgui"
#: src/net/i2p/desktopgui/InternalTrayManager.java:67
msgid "Restart I2P"
@ -38,13 +47,12 @@ msgstr "重启 I2P"
msgid "Stop I2P"
msgstr "停止 I2P"
#. Translate interface
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:26
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44
msgid "Tray icon configuration"
msgstr "托盘图标配置"
#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47
msgid "Should tray icon be enabled?"
msgstr "显示托盘图标"
msgstr "是否启用托盘图标"
#~ msgid "Browser not found"
#~ msgstr "Browser niet gevonden"
#~ msgid "The default browser for your system was not found."
#~ msgstr "De standaard webbrowser voor je systeem werd niet gevonden."

View File

@ -22,7 +22,10 @@
</classpath>
</depend>
</target>
<property name="javac.compilerargs" value="" />
<property name="require.gettext" value="true" />
<target name="compile" depends="depend">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
@ -36,7 +39,7 @@
</javac>
</target>
<target name="jar" depends="builddep, compile, jarUpToDate" unless="jar.uptodate" >
<target name="listChangedFiles" depends="jarUpToDate" if="shouldListChanges" >
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
@ -48,6 +51,11 @@
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<target name="jar" depends="builddep, compile, jarUpToDate, listChangedFiles" unless="jar.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<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" />
@ -63,6 +71,17 @@
<uptodate property="jar.uptodate" targetfile="build/i2psnark.jar" >
<srcfiles dir= "build/obj" includes="**/*.class" excludes="**/I2PSnarkServlet*.class **/messages_*.class" />
</uptodate>
<condition property="shouldListChanges" >
<and>
<not>
<isset property="jar.uptodate" />
</not>
<not>
<isset property="wjar.uptodate" />
</not>
<isset property="mtn.available" />
</and>
</condition>
</target>
<!-- Ideally we would include
@ -72,14 +91,16 @@
- So we must continue to duplicate everything in the war.
<classes dir="./build/obj" includes="**/I2PSnarkServlet*.class" />
-->
<target name="war" depends="jar, bundle, warUpToDate" unless="war.uptodate" >
<target name="war" depends="jar, bundle, warUpToDate, listChangedFiles" unless="war.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<war destfile="../i2psnark.war" webxml="../web.xml" basedir="../" includes="_icons/*" >
<!-- include only the web stuff, as of 0.7.12 the router will add i2psnark.jar to the classpath for the war -->
<classes dir="./build/obj" includes="**/web/*.class" />
<manifest>
<attribute name="Build-Date" value="${build.timestamp}" />
<attribute name="Base-Revision" value="${workspace.version}" />
<attribute name="Workspace-Changes" value="${workspace.changes}" />
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
</manifest>
</war>
</target>
@ -93,10 +114,10 @@
<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="true" >
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >
<arg value="./bundle-messages.sh" />
</exec>
<!-- multi-lang is optional -->
@ -107,15 +128,15 @@
<target name="poupdate" depends="builddep, compile">
<!-- Update the messages_*.po files. -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="windows" failifexecutionfails="true" >
<exec executable="sh" osfamily="windows" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>

View File

@ -12,6 +12,7 @@
CLASS=org.klomp.snark.web.messages
TMPFILE=build/javafiles.txt
export TZ=UTC
RC=0
if [ "$1" = "-p" ]
then
@ -67,15 +68,17 @@ do
-o ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - xgettext failed, not updating translations'
echo "ERROR - xgettext failed on ${i}, not updating translations"
rm -f ${i}t
RC=1
break
fi
msgmerge -U --backup=none $i ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - msgmerge failed, not updating translations'
echo "ERROR - msgmerge failed on ${i}, not updating translations"
rm -f ${i}t
RC=1
break
fi
rm -f ${i}t
@ -92,11 +95,13 @@ do
msgfmt --java --statistics -r $CLASS -l $LG -d build/obj $i
if [ $? -ne 0 ]
then
echo 'Warning - msgfmt failed, not updating translations'
echo "ERROR - msgfmt failed on ${i}, not updating translations"
# msgfmt leaves the class file there so the build would work the next time
find build/obj -name messages_${LG}.class -exec rm -f {} \;
RC=1
break
fi
fi
done
rm -f $TMPFILE
# todo: return failure
exit 0
exit $RC

View File

@ -44,34 +44,34 @@ import org.klomp.snark.dht.DHT;
* (but not multiple SnarkManagers, it is still static)
*/
public class I2PSnarkUtil {
private I2PAppContext _context;
private Log _log;
private final I2PAppContext _context;
private final Log _log;
private boolean _shouldProxy;
private String _proxyHost;
private int _proxyPort;
private String _i2cpHost;
private int _i2cpPort;
private Map<String, String> _opts;
private final Map<String, String> _opts;
private I2PSocketManager _manager;
private boolean _configured;
private final Set<Hash> _shitlist;
private int _maxUploaders;
private int _maxUpBW;
private int _maxConnections;
private File _tmpDir;
private final File _tmpDir;
private int _startupDelay;
private boolean _shouldUseOT;
private boolean _areFilesPublic;
private String _openTrackerString;
private DHT _dht;
public static final int DEFAULT_STARTUP_DELAY = 3;
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
public static final int MAX_CONNECTIONS = 16; // per torrent
private static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond";
public static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond";
//private static final boolean ENABLE_DHT = true;
public I2PSnarkUtil(I2PAppContext ctx) {
@ -125,6 +125,8 @@ public class I2PSnarkUtil {
// can't remove any options this way...
if (opts != null)
_opts.putAll(opts);
// this updates the session options and tells the router
setMaxUpBW(_maxUpBW);
_configured = true;
}
@ -134,6 +136,7 @@ public class I2PSnarkUtil {
}
/**
* This updates the session options and tells the router
* @param limit KBps
*/
public void setMaxUpBW(int limit) {
@ -175,6 +178,12 @@ public class I2PSnarkUtil {
public int getMaxConnections() { return _maxConnections; }
public int getStartupDelay() { return _startupDelay; }
/** @since 0.8.9 */
public boolean getFilesPublic() { return _areFilesPublic; }
/** @since 0.8.9 */
public void setFilesPublic(boolean yes) { _areFilesPublic = yes; }
/**
* Connect to the router, if we aren't already
*/
@ -433,14 +442,13 @@ public class I2PSnarkUtil {
/** @param ot non-null */
public void setOpenTrackerString(String ot) {
_opts.put(PROP_OPENTRACKERS, ot);
_openTrackerString = ot;
}
public String getOpenTrackerString() {
String rv = (String) _opts.get(PROP_OPENTRACKERS);
if (rv == null)
if (_openTrackerString == null)
return DEFAULT_OPENTRACKERS;
return rv;
return _openTrackerString;
}
/** comma delimited list open trackers to use as backups */

View File

@ -191,14 +191,21 @@ class MagnetState {
*/
public MetaInfo buildMetaInfo() throws Exception {
// top map has nothing in it but the info map (no announce)
Map<String, Object> map = new HashMap();
Map<String, BEValue> map = new HashMap();
InputStream is = new ByteArrayInputStream(metainfoBytes);
BDecoder dec = new BDecoder(is);
BEValue bev = dec.bdecodeMap();
map.put("info", bev);
MetaInfo newmeta = new MetaInfo(map);
if (!DataHelper.eq(newmeta.getInfoHash(), infohash))
if (!DataHelper.eq(newmeta.getInfoHash(), infohash)) {
// Disaster. Start over. ExtensionHandler will catch
// the IOE and disconnect the peer, hopefully we will
// find a new peer.
// TODO: Count fails and give up eventually
have = new BitField(totalChunks);
requested = new BitField(totalChunks);
throw new IOException("info hash mismatch");
}
return newmeta;
}
}

View File

@ -20,10 +20,10 @@
package org.klomp.snark;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -34,6 +34,7 @@ import java.util.Map;
import net.i2p.I2PAppContext;
import net.i2p.crypto.SHA1;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import org.klomp.snark.bencode.BDecoder;
@ -82,6 +83,12 @@ public class MetaInfo
this.piece_hashes = piece_hashes;
this.length = length;
// TODO if we add a parameter for other keys
//if (other != null) {
// otherInfo = new HashMap(2);
// otherInfo.putAll(other);
//}
this.info_hash = calculateInfoHash();
//infoMap = null;
}
@ -101,10 +108,14 @@ public class MetaInfo
* Creates a new MetaInfo from the given BDecoder. The BDecoder
* must have a complete dictionary describing the torrent.
*/
public MetaInfo(BDecoder be) throws IOException
private MetaInfo(BDecoder be) throws IOException
{
// Note that evaluation order matters here...
this(be.bdecodeMap().getMap());
byte[] origInfohash = be.get_special_map_digest();
// shouldn't ever happen
if (!DataHelper.eq(origInfohash, info_hash))
throw new InvalidBEncodingException("Infohash mismatch, please report");
}
/**
@ -116,11 +127,11 @@ public class MetaInfo
* WILL throw a InvalidBEncodingException if the given map does not
* contain a valid info dictionary.
*/
public MetaInfo(Map m) throws InvalidBEncodingException
public MetaInfo(Map<String, BEValue> m) throws InvalidBEncodingException
{
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating a metaInfo: " + m, new Exception("source"));
BEValue val = (BEValue)m.get("announce");
BEValue val = m.get("announce");
// Disabled check, we can get info from a magnet now
if (val == null) {
//throw new InvalidBEncodingException("Missing announce string");
@ -129,34 +140,37 @@ public class MetaInfo
this.announce = val.getString();
}
val = (BEValue)m.get("info");
val = m.get("info");
if (val == null)
throw new InvalidBEncodingException("Missing info map");
Map info = val.getMap();
Map<String, BEValue> info = val.getMap();
infoMap = Collections.unmodifiableMap(info);
val = (BEValue)info.get("name");
val = info.get("name");
if (val == null)
throw new InvalidBEncodingException("Missing name string");
name = val.getString();
// We could silently replace the '/', but that messes up the info hash, so just throw instead.
if (name.indexOf('/') >= 0)
throw new InvalidBEncodingException("Invalid name containing '/' " + name);
val = (BEValue)info.get("name.utf-8");
val = info.get("name.utf-8");
if (val != null)
name_utf8 = val.getString();
else
name_utf8 = null;
val = (BEValue)info.get("piece length");
val = info.get("piece length");
if (val == null)
throw new InvalidBEncodingException("Missing piece length number");
piece_length = val.getInt();
val = (BEValue)info.get("pieces");
val = info.get("pieces");
if (val == null)
throw new InvalidBEncodingException("Missing piece bytes");
piece_hashes = val.getBytes();
val = (BEValue)info.get("length");
val = info.get("length");
if (val != null)
{
// Single file case.
@ -168,7 +182,7 @@ public class MetaInfo
else
{
// Multi file case.
val = (BEValue)info.get("files");
val = info.get("files");
if (val == null)
throw new InvalidBEncodingException
("Missing length number and/or files list");
@ -189,8 +203,14 @@ public class MetaInfo
if (val == null)
throw new InvalidBEncodingException("Missing length number");
long len = val.getLong();
if (len < 0)
throw new InvalidBEncodingException("Negative file length");
m_lengths.add(Long.valueOf(len));
// check for overflowing the long
long oldTotal = l;
l += len;
if (l < oldTotal)
throw new InvalidBEncodingException("Huge total length");
val = (BEValue)desc.get("path");
if (val == null)
@ -202,8 +222,19 @@ public class MetaInfo
List<String> file = new ArrayList(path_length);
Iterator<BEValue> it = path_list.iterator();
while (it.hasNext())
file.add(it.next().getString());
while (it.hasNext()) {
String s = it.next().getString();
// We could throw an IBEE, but just silently replace instead.
if (s.indexOf('/') >= 0)
s = s.replace("/", "_");
file.add(s);
}
// quick dup check - case sensitive, etc. - Storage does a better job
for (int j = 0; j < i; j++) {
if (file.equals(m_files.get(j)))
throw new InvalidBEncodingException("Duplicate file path " + DataHelper.toString(file));
}
m_files.add(Collections.unmodifiableList(file));
@ -229,6 +260,28 @@ public class MetaInfo
info_hash = calculateInfoHash();
}
/**
* Efficiently returns the name and the 20 byte SHA1 hash of the info dictionary in a torrent file
* Caller must close stream.
*
* @param infoHashOut 20-byte out parameter
* @since 0.8.5
*/
public static String getNameAndInfoHash(InputStream in, byte[] infoHashOut) throws IOException {
BDecoder bd = new BDecoder(in);
Map<String, BEValue> m = bd.bdecodeMap().getMap();
BEValue ibev = m.get("info");
if (ibev == null)
throw new InvalidBEncodingException("Missing info map");
Map<String, BEValue> i = ibev.getMap();
BEValue rvbev = i.get("name");
if (rvbev == null)
throw new InvalidBEncodingException("Missing name");
byte[] h = bd.get_special_map_digest();
System.arraycopy(h, 0, infoHashOut, 0, 20);
return rvbev.getString();
}
/**
* Returns the string representing the URL of the tracker for this torrent.
* @return may be null!
@ -318,11 +371,13 @@ public class MetaInfo
*/
public boolean checkPiece(int piece, byte[] bs, int off, int length)
{
if (true)
//if (true)
return fast_checkPiece(piece, bs, off, length);
else
return orig_checkPiece(piece, bs, off, length);
//else
// return orig_checkPiece(piece, bs, off, length);
}
/****
private boolean orig_checkPiece(int piece, byte[] bs, int off, int length) {
// Check digest
MessageDigest sha1;
@ -342,9 +397,10 @@ public class MetaInfo
return false;
return true;
}
****/
private boolean fast_checkPiece(int piece, byte[] bs, int off, int length) {
SHA1 sha1 = new SHA1();
MessageDigest sha1 = SHA1.getInstance();
sha1.update(bs, off, length);
byte[] hash = sha1.digest();
@ -365,7 +421,7 @@ public class MetaInfo
@Override
public String toString()
{
return "MetaInfo[info_hash='" + hexencode(info_hash)
return "MetaInfo[info_hash='" + I2PSnarkUtil.toHex(info_hash)
+ "', announce='" + announce
+ "', name='" + name
+ "', files=" + files
@ -375,23 +431,6 @@ public class MetaInfo
+ "']";
}
/**
* Encode a byte array as a hex encoded string.
*/
private static String hexencode(byte[] bs)
{
StringBuilder sb = new StringBuilder(bs.length*2);
for (int i = 0; i < bs.length; i++)
{
int c = bs[i] & 0xFF;
if (c < 16)
sb.append('0');
sb.append(Integer.toHexString(c));
}
return sb.toString();
}
/**
* Creates a copy of this MetaInfo that shares everything except the
* announce URL.
@ -427,7 +466,8 @@ public class MetaInfo
/** @return an unmodifiable view of the Map */
private Map<String, BEValue> createInfoMap()
{
// if we loaded this metainfo from a file, we have the map
// If we loaded this metainfo from a file, we have the map, and we must use it
// or else we will lose any non-standard keys and corrupt the infohash.
if (infoMap != null)
return Collections.unmodifiableMap(infoMap);
// otherwise we must create it
@ -453,42 +493,55 @@ public class MetaInfo
}
info.put("files", l);
}
// TODO if we add the ability for other keys in the first constructor
//if (otherInfo != null)
// info.putAll(otherInfo);
infoMap = info;
return Collections.unmodifiableMap(infoMap);
}
private byte[] calculateInfoHash()
{
Map info = createInfoMap();
StringBuilder buf = new StringBuilder(128);
buf.append("info: ");
for (Iterator iter = info.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
Object val = entry.getValue();
buf.append(key).append('=');
if (val instanceof byte[])
buf.append(Base64.encode((byte[])val, true));
else
Map<String, BEValue> info = createInfoMap();
if (_log.shouldLog(Log.DEBUG)) {
StringBuilder buf = new StringBuilder(128);
buf.append("info: ");
for (Map.Entry<String, BEValue> entry : info.entrySet()) {
String key = entry.getKey();
Object val = entry.getValue();
buf.append(key).append('=');
buf.append(val.toString());
}
if (_log.shouldLog(Log.DEBUG))
}
_log.debug(buf.toString());
}
byte[] infoBytes = BEncoder.bencode(info);
//_log.debug("info bencoded: [" + Base64.encode(infoBytes, true) + "]");
try
{
MessageDigest digest = MessageDigest.getInstance("SHA");
MessageDigest digest = SHA1.getInstance();
byte hash[] = digest.digest(infoBytes);
if (_log.shouldLog(Log.DEBUG))
_log.debug("info hash: [" + net.i2p.data.Base64.encode(hash) + "]");
_log.debug("info hash: " + I2PSnarkUtil.toHex(hash));
return hash;
}
catch(NoSuchAlgorithmException nsa)
{
throw new InternalError(nsa.toString());
}
}
/** @since 0.8.5 */
public static void main(String[] args) {
if (args.length <= 0) {
System.err.println("Usage: MetaInfo files...");
return;
}
for (int i = 0; i < args.length; i++) {
InputStream in = null;
try {
in = new FileInputStream(args[i]);
MetaInfo meta = new MetaInfo(in);
System.out.println(args[i] + " InfoHash: " + I2PSnarkUtil.toHex(meta.getInfoHash()));
} catch (IOException ioe) {
System.err.println("Error in file " + args[i] + ": " + ioe);
} finally {
try { if (in != null) in.close(); } catch (IOException ioe) {}
}
}
}
}

View File

@ -130,7 +130,8 @@ public class PeerAcceptor
}
}
private static final int LOOKAHEAD_SIZE = "19".length() +
/** 48 */
private static final int LOOKAHEAD_SIZE = 1 + // chr(19)
"BitTorrent protocol".length() +
8 + // blank, reserved
20; // infohash
@ -144,7 +145,7 @@ public class PeerAcceptor
if (read != buf.length)
throw new IOException("Unable to read the hash (read " + read + ")");
byte rv[] = new byte[20];
System.arraycopy(buf, buf.length-rv.length-1, rv, 0, rv.length);
System.arraycopy(buf, buf.length-rv.length, rv, 0, rv.length);
return rv;
}
}

View File

@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.TimerTask;
import net.i2p.I2PAppContext;
@ -32,7 +31,7 @@ import net.i2p.I2PAppContext;
* TimerTask that checks for good/bad up/downloader. Works together
* with the PeerCoordinator to select which Peers get (un)choked.
*/
class PeerCheckerTask extends TimerTask
class PeerCheckerTask implements Runnable
{
private static final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000);
@ -54,8 +53,6 @@ class PeerCheckerTask extends TimerTask
List<Peer> peerList = coordinator.peerList();
if (peerList.isEmpty() || coordinator.halted()) {
coordinator.setRateHistory(0, 0);
if (coordinator.halted())
cancel();
return;
}

View File

@ -342,6 +342,11 @@ public class PeerCoordinator implements PeerListener
private int getMaxConnections() {
if (metainfo == null)
return 6;
int pieces = metainfo.getPieces();
if (pieces <= 2)
return 4;
if (pieces <= 5)
return 6;
int size = metainfo.getPieceLength(0);
int max = _util.getMaxConnections();
if (size <= 512*1024 || completed())
@ -426,6 +431,10 @@ public class PeerCoordinator implements PeerListener
_log.info("New connection to peer: " + peer + " for " + name);
}
// We may have gotten the metainfo after the peer was created.
if (metainfo != null)
peer.setMetaInfo(metainfo);
// Add it to the beginning of the list.
// And try to optimistically make it a uploader.
// Can't add to beginning since we converted from a List to a Queue
@ -783,6 +792,8 @@ public class PeerCoordinator implements PeerListener
/**
* Returns a byte array containing the requested piece or null of
* the piece is unknown.
*
* @throws RuntimeException on IOE getting the data
*/
public byte[] gotRequest(Peer peer, int piece, int off, int len)
{
@ -798,8 +809,11 @@ public class PeerCoordinator implements PeerListener
catch (IOException ioe)
{
snark.stopTorrent();
_log.error("Error reading the storage for " + metainfo.getName(), ioe);
throw new RuntimeException("B0rked");
String msg = "Error reading the storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
_log.error(msg, ioe);
SnarkManager.instance().addMessage(msg);
SnarkManager.instance().addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
throw new RuntimeException(msg, ioe);
}
}
@ -829,6 +843,8 @@ public class PeerCoordinator implements PeerListener
* Returns false if the piece is no good (according to the hash).
* In that case the peer that supplied the piece should probably be
* blacklisted.
*
* @throws RuntimeException on IOE saving the piece
*/
public boolean gotPiece(Peer peer, int piece, byte[] bs)
{
@ -872,8 +888,11 @@ public class PeerCoordinator implements PeerListener
catch (IOException ioe)
{
snark.stopTorrent();
_log.error("Error writing storage for " + metainfo.getName(), ioe);
throw new RuntimeException("B0rked");
String msg = "Error writing storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
_log.error(msg, ioe);
SnarkManager.instance().addMessage(msg);
SnarkManager.instance().addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
throw new RuntimeException(msg, ioe);
}
wantedPieces.remove(p);
}

View File

@ -21,7 +21,6 @@
package org.klomp.snark;
import java.util.Iterator;
import java.util.TimerTask;
import net.i2p.data.DataHelper;
@ -29,7 +28,7 @@ import net.i2p.data.DataHelper;
* TimerTask that monitors the peers and total up/download speeds.
* Works together with the main Snark class to report periodical statistics.
*/
class PeerMonitorTask extends TimerTask
class PeerMonitorTask implements Runnable
{
final static long MONITOR_PERIOD = 10 * 1000; // Ten seconds.
private static final long KILOPERSECOND = 1024 * (MONITOR_PERIOD / 1000);

View File

@ -496,10 +496,14 @@ class PeerState implements DataLoader
}
/**
* Switch from magnet mode to normal mode
* Switch from magnet mode to normal mode.
* If we already have the metainfo, this does nothing.
* @param meta non-null
* @since 0.8.4
*/
public void setMetaInfo(MetaInfo meta) {
if (metainfo != null)
return;
BitField oldBF = bitfield;
if (oldBF != null) {
if (oldBF.size() != meta.getPieces())
@ -511,7 +515,7 @@ class PeerState implements DataLoader
//bitfield = new BitField(meta.getPieces());
}
metainfo = meta;
if (bitfield.count() > 0)
if (bitfield != null && bitfield.count() > 0)
setInteresting(true);
}

View File

@ -32,16 +32,12 @@ import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.data.Destination;
import net.i2p.util.I2PThread;
import org.klomp.snark.bencode.BDecoder;
/**
* Main Snark program startup class.
*
@ -360,7 +356,7 @@ public class Snark
in = new FileInputStream(torrentFile);
}
}
meta = new MetaInfo(new BDecoder(in));
meta = new MetaInfo(in);
infoHash = meta.getInfoHash();
}
catch(IOException ioe)
@ -589,7 +585,7 @@ public class Snark
pc.halt();
Storage st = storage;
if (st != null) {
boolean changed = storage.changed;
boolean changed = storage.isChanged();
try {
storage.close();
} catch (IOException ioe) {
@ -783,6 +779,26 @@ public class Snark
return -1;
}
/**
* @return exact value. or -1 if no storage yet.
* getNeeded() * pieceLength(0) isn't accurate if last piece
* is still needed.
* @since 0.8.9
*/
public long getRemainingLength() {
if (meta != null && storage != null) {
long needed = storage.needed();
long length0 = meta.getPieceLength(0);
long remaining = needed * length0;
// fixup if last piece is needed
int last = meta.getPieces() - 1;
if (last != 0 && !storage.getBitField().get(last))
remaining -= length0 - meta.getPieceLength(last);
return remaining;
}
return -1;
}
/**
* @return number of pieces still needed (magnet mode or not), or -1 if unknown
* @since 0.8.4
@ -1013,7 +1029,7 @@ public class Snark
//if (debug >= INFO && t != null)
// t.printStackTrace();
stopTorrent();
throw new RuntimeException(s + (t == null ? "" : ": " + t));
throw new RuntimeException(s, t);
}
/**
@ -1111,7 +1127,7 @@ public class Snark
allChecked = true;
checking = false;
if (storage.changed && completeListener != null)
if (storage.isChanged() && completeListener != null)
completeListener.updateStatus(this);
}

View File

@ -3,6 +3,7 @@ package org.klomp.snark;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
@ -48,14 +49,14 @@ public class SnarkManager implements Snark.CompleteListener {
private final Object _addSnarkLock;
private /* FIXME final FIXME */ File _configFile;
private Properties _config;
private I2PAppContext _context;
private Log _log;
private final I2PAppContext _context;
private final Log _log;
private final List _messages;
private I2PSnarkUtil _util;
private final I2PSnarkUtil _util;
private PeerCoordinatorSet _peerCoordinatorSet;
private ConnectionAcceptor _connectionAcceptor;
private Thread _monitor;
private boolean _running;
private volatile boolean _running;
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
@ -71,17 +72,23 @@ public class SnarkManager implements Snark.CompleteListener {
public static final String PROP_META_MAGNET_PREFIX = "i2psnark.magnet.";
private static final String CONFIG_FILE = "i2psnark.config";
public static final String PROP_FILES_PUBLIC = "i2psnark.filesPublic";
public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops
public static final String DEFAULT_AUTO_START = "false";
public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
public static final String DEFAULT_LINK_PREFIX = "file:///";
//public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
//public static final String DEFAULT_LINK_PREFIX = "file:///";
public static final String PROP_STARTUP_DELAY = "i2psnark.startupDelay";
public static final String PROP_REFRESH_DELAY = "i2psnark.refreshSeconds";
public static final String PROP_THEME = "i2psnark.theme";
public static final String DEFAULT_THEME = "ubergine";
private static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
public static final int MIN_UP_BW = 2;
public static final int DEFAULT_MAX_UP_BW = 10;
public static final int DEFAULT_STARTUP_DELAY = 3;
public static final int DEFAULT_REFRESH_DELAY_SECS = 60;
private SnarkManager() {
_snarks = new ConcurrentHashMap();
_magnets = new ConcurrentHashSet();
@ -136,20 +143,57 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
public boolean shouldAutoStart() {
return Boolean.valueOf(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START+"")).booleanValue();
/**
* @return default false
* @since 0.8.9
*/
public boolean areFilesPublic() {
return Boolean.valueOf(_config.getProperty(PROP_FILES_PUBLIC)).booleanValue();
}
public boolean shouldAutoStart() {
return Boolean.valueOf(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START)).booleanValue();
}
/****
public String linkPrefix() {
return _config.getProperty(PROP_LINK_PREFIX, DEFAULT_LINK_PREFIX + getDataDir().getAbsolutePath() + File.separatorChar);
}
private int getStartupDelayMinutes() {
return Integer.valueOf(_config.getProperty(PROP_STARTUP_DELAY)).intValue();
****/
/**
* @return -1 for never
* @since 0.8.9
*/
public int getRefreshDelaySeconds() {
try {
return Integer.parseInt(_config.getProperty(PROP_REFRESH_DELAY));
} catch (NumberFormatException nfe) {
return DEFAULT_REFRESH_DELAY_SECS;
}
}
private int getStartupDelayMinutes() {
try {
return Integer.parseInt(_config.getProperty(PROP_STARTUP_DELAY));
} catch (NumberFormatException nfe) {
return DEFAULT_STARTUP_DELAY;
}
}
public File getDataDir() {
String dir = _config.getProperty(PROP_DIR, "i2psnark");
File f = new SecureDirectory(dir);
if (!f.isAbsolute())
f = new SecureDirectory(_context.getAppDir(), dir);
File f;
if (areFilesPublic())
f = new File(dir);
else
f = new SecureDirectory(dir);
if (!f.isAbsolute()) {
if (areFilesPublic())
f = new File(_context.getAppDir(), dir);
else
f = new SecureDirectory(_context.getAppDir(), dir);
}
return f;
}
@ -187,8 +231,10 @@ public class SnarkManager implements Snark.CompleteListener {
_config.setProperty(PROP_DIR, "i2psnark");
if (!_config.containsKey(PROP_AUTO_START))
_config.setProperty(PROP_AUTO_START, DEFAULT_AUTO_START);
if (!_config.containsKey(PROP_REFRESH_DELAY))
_config.setProperty(PROP_REFRESH_DELAY, Integer.toString(DEFAULT_REFRESH_DELAY_SECS));
if (!_config.containsKey(PROP_STARTUP_DELAY))
_config.setProperty(PROP_STARTUP_DELAY, "" + DEFAULT_STARTUP_DELAY);
_config.setProperty(PROP_STARTUP_DELAY, Integer.toString(DEFAULT_STARTUP_DELAY));
if (!_config.containsKey(PROP_THEME))
_config.setProperty(PROP_THEME, DEFAULT_THEME);
updateConfig();
@ -258,10 +304,11 @@ public class SnarkManager implements Snark.CompleteListener {
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
_util.setStartupDelay(getInt(PROP_STARTUP_DELAY, DEFAULT_STARTUP_DELAY));
String ot = _config.getProperty(I2PSnarkUtil.PROP_OPENTRACKERS);
_util.setFilesPublic(areFilesPublic());
String ot = _config.getProperty(PROP_OPENTRACKERS);
if (ot != null)
_util.setOpenTrackerString(ot);
String useOT = _config.getProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS);
String useOT = _config.getProperty(PROP_USE_OPENTRACKERS);
boolean bOT = useOT == null || Boolean.valueOf(useOT).booleanValue();
_util.setUseOpenTrackers(bOT);
getDataDir().mkdirs();
@ -278,7 +325,8 @@ public class SnarkManager implements Snark.CompleteListener {
return defaultVal;
}
public void updateConfig(String dataDir, boolean autoStart, String startDelay, String seedPct, String eepHost,
public void updateConfig(String dataDir, boolean filesPublic, boolean autoStart, String refreshDelay,
String startDelay, String seedPct, String eepHost,
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers, String theme) {
boolean changed = false;
@ -333,19 +381,34 @@ public class SnarkManager implements Snark.CompleteListener {
changed = true;
_config.setProperty(PROP_STARTUP_DELAY, "" + minutes);
addMessage(_("Startup delay changed to {0}", DataHelper.formatDuration2(minutes * 60 * 1000)));
}
}
}
// FIXME do this even if == null
if (i2cpHost != null) {
if (refreshDelay != null) {
try {
int secs = Integer.parseInt(refreshDelay);
if (secs != getRefreshDelaySeconds()) {
changed = true;
_config.setProperty(PROP_REFRESH_DELAY, refreshDelay);
if (secs >= 0)
addMessage(_("Refresh time changed to {0}", DataHelper.formatDuration2(secs * 1000)));
else
addMessage(_("Refresh disabled"));
}
} catch (NumberFormatException nfe) {}
}
// Start of I2CP stuff.
// i2cpHost will generally be null since it is hidden from the form if in router context.
int oldI2CPPort = _util.getI2CPPort();
String oldI2CPHost = _util.getI2CPHost();
int port = oldI2CPPort;
if (i2cpPort != null) {
try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {}
}
String host = oldI2CPHost;
Map opts = new HashMap();
Map<String, String> opts = new HashMap();
if (i2cpOpts == null) i2cpOpts = "";
StringTokenizer tok = new StringTokenizer(i2cpOpts, " \t\n");
while (tok.hasMoreTokens()) {
@ -354,7 +417,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (split > 0)
opts.put(pair.substring(0, split), pair.substring(split+1));
}
Map oldOpts = new HashMap();
Map<String, String> oldOpts = new HashMap();
String oldI2CPOpts = _config.getProperty(PROP_I2CP_OPTS);
if (oldI2CPOpts == null) oldI2CPOpts = "";
tok = new StringTokenizer(oldI2CPOpts, " \t\n");
@ -365,37 +428,39 @@ public class SnarkManager implements Snark.CompleteListener {
oldOpts.put(pair.substring(0, split), pair.substring(split+1));
}
if ( (i2cpHost.trim().length() > 0) && (port > 0) &&
((!host.equals(i2cpHost) ||
(port != _util.getI2CPPort()) ||
(!oldOpts.equals(opts)))) ) {
boolean reconnect = i2cpHost != null && i2cpHost.trim().length() > 0 && port > 0 &&
(port != _util.getI2CPPort() || !oldI2CPHost.equals(i2cpHost));
if (reconnect || !oldOpts.equals(opts)) {
boolean snarksActive = false;
Set names = listTorrentFiles();
for (Iterator iter = names.iterator(); iter.hasNext(); ) {
Snark snark = getTorrent((String)iter.next());
if ( (snark != null) && (!snark.isStopped()) ) {
snarksActive = true;
break;
if (reconnect) {
for (Snark snark : _snarks.values()) {
if (!snark.isStopped()) {
snarksActive = true;
break;
}
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
+ "] oldOpts [" + oldOpts + "]");
if (snarksActive) {
Properties p = new Properties();
p.putAll(opts);
_util.setI2CPConfig(i2cpHost, port, p);
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
addMessage(_("I2CP and tunnel changes will take effect after stopping all torrents"));
if (_log.shouldLog(Log.DEBUG))
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
+ "] oldOpts [" + oldOpts + "]");
} else if (!reconnect) {
// The usual case, the other two are if not in router context
_config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim());
addMessage(_("I2CP options changed to {0}", i2cpOpts));
_util.setI2CPConfig(oldI2CPHost, oldI2CPPort, opts);
} else {
if (_util.connected()) {
_util.disconnect();
addMessage(_("Disconnecting old I2CP destination"));
}
Properties p = new Properties();
p.putAll(opts);
addMessage(_("I2CP settings changed to {0}", i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")"));
_util.setI2CPConfig(i2cpHost, port, p);
addMessage(_("I2CP settings changed to {0}", i2cpHost + ':' + port + ' ' + i2cpOpts));
_util.setI2CPConfig(i2cpHost, port, opts);
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
boolean ok = _util.connect();
if (!ok) {
@ -409,22 +474,29 @@ public class SnarkManager implements Snark.CompleteListener {
_config.setProperty(PROP_I2CP_HOST, i2cpHost.trim());
_config.setProperty(PROP_I2CP_PORT, "" + port);
_config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim());
changed = true;
// no PeerAcceptors/I2PServerSockets to deal with, since all snarks are inactive
for (Iterator iter = names.iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
Snark snark = getTorrent(name);
if (snark != null && snark.restartAcceptor()) {
for (Snark snark : _snarks.values()) {
if (snark.restartAcceptor()) {
addMessage(_("I2CP listener restarted for \"{0}\"", snark.getBaseName()));
}
}
}
}
changed = true;
}
} // reconnect || changed options
if (areFilesPublic() != filesPublic) {
_config.setProperty(PROP_FILES_PUBLIC, Boolean.toString(filesPublic));
_util.setFilesPublic(filesPublic);
if (filesPublic)
addMessage(_("New files will be publicly readable"));
else
addMessage(_("New files will not be publicly readable"));
changed = true;
}
if (shouldAutoStart() != autoStart) {
_config.setProperty(PROP_AUTO_START, autoStart + "");
_config.setProperty(PROP_AUTO_START, Boolean.toString(autoStart));
if (autoStart)
addMessage(_("Enabled autostart"));
else
@ -432,7 +504,7 @@ public class SnarkManager implements Snark.CompleteListener {
changed = true;
}
if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
_config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + "");
_config.setProperty(PROP_USE_OPENTRACKERS, useOpenTrackers + "");
if (useOpenTrackers)
addMessage(_("Enabled open trackers - torrent restart required to take effect."));
else
@ -442,7 +514,7 @@ public class SnarkManager implements Snark.CompleteListener {
}
if (openTrackers != null) {
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(_util.getOpenTrackerString())) {
_config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim());
_config.setProperty(PROP_OPENTRACKERS, openTrackers.trim());
_util.setOpenTrackerString(openTrackers);
addMessage(_("Open Tracker list changed - torrent restart required to take effect."));
changed = true;
@ -489,7 +561,7 @@ public class SnarkManager implements Snark.CompleteListener {
* Grab the torrent given the (canonical) filename of the .torrent file
* @return Snark or null
*/
public Snark getTorrent(String filename) { synchronized (_snarks) { return (Snark)_snarks.get(filename); } }
public Snark getTorrent(String filename) { synchronized (_snarks) { return _snarks.get(filename); } }
/**
* Grab the torrent given the base name of the storage
@ -572,6 +644,9 @@ public class SnarkManager implements Snark.CompleteListener {
}
try {
// This is somewhat wasteful as this metainfo is thrown away,
// the real one is created in the Snark constructor.
// TODO: Make a Snark constructor where we pass the MetaInfo in as a parameter.
MetaInfo info = new MetaInfo(fis);
try {
fis.close();
@ -622,6 +697,7 @@ public class SnarkManager implements Snark.CompleteListener {
return;
} catch (OutOfMemoryError oom) {
addMessage(_("ERROR - Out of memory, cannot create torrent from {0}", sfile.getName()) + ": " + oom.getMessage());
return;
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
@ -719,7 +795,7 @@ public class SnarkManager implements Snark.CompleteListener {
// so addTorrent won't recheck
saveTorrentStatus(metainfo, bitfield, null); // no file priorities
try {
locked_writeMetaInfo(metainfo, filename);
locked_writeMetaInfo(metainfo, filename, areFilesPublic());
// hold the lock for a long time
addTorrent(filename, dontAutoStart);
} catch (IOException ioe) {
@ -750,7 +826,8 @@ public class SnarkManager implements Snark.CompleteListener {
_log.error("Failed to write torrent file to " + filename);
return;
}
SecureFileOutputStream.setPerms(new File(filename));
if (!areFilesPublic())
SecureFileOutputStream.setPerms(new File(filename));
// hold the lock for a long time
addTorrent(filename);
}
@ -765,13 +842,16 @@ public class SnarkManager implements Snark.CompleteListener {
* Must be a filesystem-safe name.
* @since 0.8.4
*/
private static void locked_writeMetaInfo(MetaInfo metainfo, String filename) throws IOException {
private static void locked_writeMetaInfo(MetaInfo metainfo, String filename, boolean areFilesPublic) throws IOException {
File file = new File(filename);
if (file.exists())
throw new IOException("Cannot overwrite an existing .torrent file: " + file.getPath());
OutputStream out = null;
try {
out = new SecureFileOutputStream(filename);
if (areFilesPublic)
out = new FileOutputStream(filename);
else
out = new SecureFileOutputStream(filename);
out.write(metainfo.getTorrentData());
} catch (IOException ioe) {
// remove any partial
@ -779,7 +859,7 @@ public class SnarkManager implements Snark.CompleteListener {
throw ioe;
} finally {
try {
if (out == null)
if (out != null)
out.close();
} catch (IOException ioe) {}
}
@ -979,6 +1059,8 @@ public class SnarkManager implements Snark.CompleteListener {
} else if (info.getPieceLength(0) > Storage.MAX_PIECE_SIZE) {
return _("Pieces are too large in \"{0}\" ({1}B), deleting it.", info.getName(), DataHelper.formatSize2(info.getPieceLength(0))) + ' ' +
_("Limit is {0}B", DataHelper.formatSize2(Storage.MAX_PIECE_SIZE));
} else if (info.getTotalLength() <= 0) {
return _("Torrent \"{0}\" has no data, deleting it!", info.getName());
} else if (info.getTotalLength() > Storage.MAX_TOTAL_SIZE) {
System.out.println("torrent info: " + info.toString());
List lengths = info.getLengths();
@ -1083,7 +1165,7 @@ public class SnarkManager implements Snark.CompleteListener {
// although the user will see the default until then
getBWLimit();
boolean doMagnets = true;
while (true) {
while (_running) {
File dir = getDataDir();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Directory Monitor loop over " + dir.getAbsolutePath());
@ -1096,8 +1178,12 @@ public class SnarkManager implements Snark.CompleteListener {
_log.error("Error in the DirectoryMonitor", e);
}
if (doMagnets) {
addMagnets();
doMagnets = false;
try {
addMagnets();
doMagnets = false;
} catch (Exception e) {
_log.error("Error in the DirectoryMonitor", e);
}
}
try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
}
@ -1160,7 +1246,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (announce != null)
meta = meta.reannounce(announce);
synchronized (_snarks) {
locked_writeMetaInfo(meta, name);
locked_writeMetaInfo(meta, name, areFilesPublic());
// put it in the list under the new name
_snarks.remove(snark.getName());
_snarks.put(name, snark);
@ -1216,6 +1302,8 @@ public class SnarkManager implements Snark.CompleteListener {
}
Set<String> existingNames = listTorrentFiles();
if (_log.shouldLog(Log.DEBUG))
_log.debug("DirMon found: " + DataHelper.toString(foundNames) + " existing: " + DataHelper.toString(existingNames));
// lets find new ones first...
for (int i = 0; i < foundNames.size(); i++) {
if (existingNames.contains(foundNames.get(i))) {
@ -1282,8 +1370,9 @@ public class SnarkManager implements Snark.CompleteListener {
// , "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://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
,"Diftracker", "http://n--XWjHjUPjnMNrSwXA2OYXpMIUL~u4FNXnrt2HtjK3y6j~4SOClyyeKzd0zRPlixxkCe2wfBIYye3bZsaqAD8bd0QMmowxbq91WpjsPfKMiphJbePKXtYAVARiy0cqyvh1d2LyDE-6wkvgaw45hknmS0U-Dg3YTJZbAQRU2SKXgIlAbWCv4R0kDFBLEVpReDiJef3rzAWHiW8yjmJuJilkYjMwlfRjw8xx1nl2s~yhlljk1pl13jGYb0nfawQnuOWeP-ASQWvAAyVgKvZRJE2O43S7iveu9piuv7plXWbt36ef7ndu2GNoNyPOBdpo9KUZ-NOXm4Kgh659YtEibL15dEPAOdxprY0sYUurVw8OIWqrpX7yn08nbi6qHVGqQwTpxH35vkL8qrCbm-ym7oQJQnNmSDrNTyWYRFSq5s5~7DAdFDzqRPW-pX~g0zEivWj5tzkhvG9rVFgFo0bpQX3X0PUAV9Xbyf8u~v8Zbr9K1pCPqBq9XEr4TqaLHw~bfAAAA.i2p/announce.php=http://diftracker.i2p/"
// , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
// ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
};
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */

View File

@ -23,6 +23,7 @@ package org.klomp.snark;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -47,16 +48,16 @@ public class Storage
private int[] priorities;
private final StorageListener listener;
private I2PSnarkUtil _util;
private final I2PSnarkUtil _util;
private /* FIXME final FIXME */ BitField bitfield; // BitField to represent the pieces
private int needed; // Number of pieces needed
private boolean _probablyComplete; // use this to decide whether to open files RO
// XXX - Not always set correctly
int piece_size;
int pieces;
boolean changed;
private final int piece_size;
private final int pieces;
private final long total_length;
private boolean changed;
/** The default piece size. */
private static final int MIN_PIECE_SIZE = 256*1024;
@ -81,6 +82,9 @@ public class Storage
needed = metainfo.getPieces();
_probablyComplete = false;
bitfield = new BitField(needed);
piece_size = metainfo.getPieceLength(0);
pieces = needed;
total_length = metainfo.getTotalLength();
}
/**
@ -108,17 +112,20 @@ public class Storage
lengthsList.add(Long.valueOf(length));
}
piece_size = MIN_PIECE_SIZE;
pieces = (int) ((total - 1)/piece_size) + 1;
while (pieces > MAX_PIECES && piece_size < MAX_PIECE_SIZE)
{
piece_size = piece_size*2;
pieces = (int) ((total - 1)/piece_size) +1;
}
if (total <= 0)
throw new IOException("Torrent contains no data");
int pc_size = MIN_PIECE_SIZE;
int pcs = (int) ((total - 1)/pc_size) + 1;
while (pcs > MAX_PIECES && pc_size < MAX_PIECE_SIZE)
{
pc_size *= 2;
pcs = (int) ((total - 1)/pc_size) +1;
}
piece_size = pc_size;
pieces = pcs;
total_length = total;
// Note that piece_hashes and the bitfield will be filled after
// the MetaInfo is created.
byte[] piece_hashes = new byte[20*pieces];
bitfield = new BitField(pieces);
needed = 0;
@ -142,69 +149,26 @@ public class Storage
lengthsList = null;
}
// Note that the piece_hashes are not correctly setup yet.
byte[] piece_hashes = fast_digestCreate();
metainfo = new MetaInfo(announce, baseFile.getName(), null, files,
lengthsList, piece_size, piece_hashes, total);
}
// Creates piece hashes for a new storage.
// This does NOT create the files, just the hashes
public void create() throws IOException
{
// if (true) {
fast_digestCreate();
// } else {
// orig_digestCreate();
// }
}
/*
private void orig_digestCreate() throws IOException {
// Calculate piece_hashes
MessageDigest digest = null;
try
{
digest = MessageDigest.getInstance("SHA");
}
catch(NoSuchAlgorithmException nsa)
{
throw new InternalError(nsa.toString());
}
byte[] piece_hashes = metainfo.getPieceHashes();
byte[] piece = new byte[piece_size];
for (int i = 0; i < pieces; i++)
{
int length = getUncheckedPiece(i, piece);
digest.update(piece, 0, length);
byte[] hash = digest.digest();
for (int j = 0; j < 20; j++)
piece_hashes[20 * i + j] = hash[j];
bitfield.set(i);
if (listener != null)
listener.storageChecked(this, i, true);
}
if (listener != null)
listener.storageAllChecked(this);
// Reannounce to force recalculating the info_hash.
metainfo = metainfo.reannounce(metainfo.getAnnounce());
}
*/
/** FIXME we can run out of fd's doing this,
/**
* Creates piece hashes for a new storage.
* This does NOT create the files, just the hashes.
* Also sets all the bitfield bits.
*
* FIXME we can run out of fd's doing this,
* maybe some sort of global close-RAF-right-away flag
* would do the trick */
private void fast_digestCreate() throws IOException {
* would do the trick
*/
private byte[] fast_digestCreate() throws IOException {
// Calculate piece_hashes
SHA1 digest = new SHA1();
MessageDigest digest = SHA1.getInstance();
byte[] piece_hashes = metainfo.getPieceHashes();
byte[] piece_hashes = new byte[20 * pieces];
byte[] piece = new byte[piece_size];
for (int i = 0; i < pieces; i++)
@ -212,14 +176,10 @@ public class Storage
int length = getUncheckedPiece(i, piece);
digest.update(piece, 0, length);
byte[] hash = digest.digest();
for (int j = 0; j < 20; j++)
piece_hashes[20 * i + j] = hash[j];
System.arraycopy(hash, 0, piece_hashes, 20 * i, 20);
bitfield.set(i);
}
// Reannounce to force recalculating the info_hash.
metainfo = metainfo.reannounce(metainfo.getAnnounce());
return piece_hashes;
}
private void getFiles(File base) throws IOException
@ -294,6 +254,14 @@ public class Storage
return needed == 0;
}
/**
* Has the storage changed since instantiation?
* @since 0.8.5
*/
public boolean isChanged() {
return changed;
}
/**
* @param file canonical path (non-directory)
* @return number of bytes remaining; -1 if unknown file
@ -315,14 +283,13 @@ public class Storage
if (f != null && canonical.equals(file)) {
if (complete())
return 0;
int psz = metainfo.getPieceLength(0);
int psz = piece_size;
long start = bytes;
long end = start + lengths[i];
int pc = (int) (bytes / psz);
long rv = 0;
if (!bitfield.get(pc))
rv = Math.min(psz - (start % psz), lengths[i]);
int pieces = metainfo.getPieces();
for (int j = pc + 1; (((long)j) * psz) < end && j < pieces; j++) {
if (!bitfield.get(j)) {
if (((long)(j+1))*psz < end)
@ -418,7 +385,7 @@ public class Storage
int file = 0;
long pcEnd = -1;
long fileEnd = lengths[0] - 1;
int psz = metainfo.getPieceLength(0);
int psz = piece_size;
for (int i = 0; i < rv.length; i++) {
pcEnd += psz;
int pri = priorities[file];
@ -466,10 +433,15 @@ public class Storage
/** use a saved bitfield and timestamp from a config file */
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
{
File base = new SecureFile(rootDir, filterName(metainfo.getName()));
File base;
boolean areFilesPublic = _util.getFilesPublic();
if (areFilesPublic)
base = new File(rootDir, filterName(metainfo.getName()));
else
base = new SecureFile(rootDir, filterName(metainfo.getName()));
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
List files = metainfo.getFiles();
List<List<String>> files = metainfo.getFiles();
if (files == null)
{
// Create base as file.
@ -500,7 +472,7 @@ public class Storage
if (!base.mkdir() && !base.isDirectory())
throw new IOException("Could not create directory " + base);
List ls = metainfo.getLengths();
List<Long> ls = metainfo.getLengths();
int size = files.size();
long total = 0;
lengths = new long[size];
@ -511,8 +483,28 @@ public class Storage
RAFfile = new File[size];
for (int i = 0; i < size; i++)
{
File f = createFileFromNames(base, (List)files.get(i));
lengths[i] = ((Long)ls.get(i)).longValue();
List<String> path = files.get(i);
File f = createFileFromNames(base, path, areFilesPublic);
// dup file name check after filtering
for (int j = 0; j < i; j++) {
if (f.equals(RAFfile[j])) {
// Rename and start the check over again
// Copy path since metainfo list is unmodifiable
path = new ArrayList(path);
int last = path.size() - 1;
String lastPath = path.get(last);
int dot = lastPath.lastIndexOf('.');
// foo.mp3 -> foo_.mp3; foo -> _foo
if (dot >= 0)
lastPath = lastPath.substring(0, dot) + '_' + lastPath.substring(dot);
else
lastPath = '_' + lastPath;
path.set(last, lastPath);
f = createFileFromNames(base, path, areFilesPublic);
j = 0;
}
}
lengths[i] = ls.get(i).longValue();
RAFlock[i] = new Object();
RAFfile[i] = f;
total += lengths[i];
@ -551,43 +543,27 @@ public class Storage
}
/**
* Reopen the file descriptors for a restart
* Do existence check but no length check or data reverification
* Doesn't really reopen the file descriptors for a restart.
* Just does an existence check but no length check or data reverification
*
* @param rootDir ignored
* @throws IOE on fail
*/
public void reopen(String rootDir) throws IOException
{
File base = new File(rootDir, filterName(metainfo.getName()));
List files = metainfo.getFiles();
if (files == null)
{
// Reopen base as file.
_util.debug("Reopening file: " + base, Snark.NOTICE);
if (!base.exists())
throw new IOException("Could not reopen file " + base);
}
else
{
// Reopen base as dir.
_util.debug("Reopening directory: " + base, Snark.NOTICE);
if (!base.isDirectory())
throw new IOException("Could not reopen directory " + base);
int size = files.size();
for (int i = 0; i < size; i++)
{
File f = getFileFromNames(base, (List)files.get(i));
if (!f.exists())
throw new IOException("Could not reopen file " + f);
}
if (RAFfile == null)
throw new IOException("Storage not checked yet");
for (int i = 0; i < RAFfile.length; i++) {
if (!RAFfile[i].exists())
throw new IOException("File does not exist: " + RAFfile[i]);
}
}
private static final char[] ILLEGAL = new char[] {
'<', '>', ':', '"', '/', '\\', '|', '?', '*',
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
0x7f };
/**
* Removes 'suspicious' characters from the given file name.
@ -609,17 +585,25 @@ public class Storage
return rv;
}
private File createFileFromNames(File base, List names) throws IOException
/**
* Note that filtering each path element individually may lead to
* things going in the wrong place if there are duplicates
* in intermediate path elements after filtering.
*/
private static File createFileFromNames(File base, List<String> names, boolean areFilesPublic) throws IOException
{
File f = null;
Iterator it = names.iterator();
Iterator<String> it = names.iterator();
while (it.hasNext())
{
String name = filterName((String)it.next());
String name = filterName(it.next());
if (it.hasNext())
{
// Another dir in the hierarchy.
f = new File(base, name);
if (areFilesPublic)
f = new File(base, name);
else
f = new SecureFile(base, name);
if (!f.mkdir() && !f.isDirectory())
throw new IOException("Could not create directory " + f);
base = f;
@ -627,7 +611,10 @@ public class Storage
else
{
// The final element (file) in the hierarchy.
f = new SecureFile(base, name);
if (areFilesPublic)
f = new File(base, name);
else
f = new SecureFile(base, name);
if (!f.createNewFile() && !f.exists())
throw new IOException("Could not create file " + f);
}
@ -635,12 +622,12 @@ public class Storage
return f;
}
public static File getFileFromNames(File base, List names)
public static File getFileFromNames(File base, List<String> names)
{
Iterator it = names.iterator();
Iterator<String> it = names.iterator();
while (it.hasNext())
{
String name = filterName((String)it.next());
String name = filterName(it.next());
base = new File(base, name);
}
return base;
@ -690,7 +677,10 @@ public class Storage
} catch (IOException ioe) {}
}
} else {
_util.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR);
String msg = "File '" + names[i] + "' exists, but has wrong length (expected " +
lengths[i] + " but found " + length + ") - repairing corruption";
SnarkManager.instance().addMessage(msg);
_util.debug(msg, Snark.ERROR);
changed = true;
_probablyComplete = false; // to force RW
synchronized(RAFlock[i]) {
@ -706,8 +696,7 @@ public class Storage
// Check which pieces match and which don't
if (resume)
{
pieces = metainfo.getPieces();
byte[] piece = new byte[metainfo.getPieceLength(0)];
byte[] piece = new byte[piece_size];
int file = 0;
long fileEnd = lengths[0];
long pieceEnd = 0;
@ -773,27 +762,19 @@ public class Storage
openRAF(nr, false); // RW
// XXX - Is this the best way to make sure we have enough space for
// the whole file?
long remaining = lengths[nr];
if (listener != null)
listener.storageCreateFile(this, names[nr], lengths[nr]);
final int ZEROBLOCKSIZE = metainfo.getPieceLength(0);
byte[] zeros;
try {
zeros = new byte[ZEROBLOCKSIZE];
} catch (OutOfMemoryError oom) {
throw new IOException(oom.toString());
listener.storageCreateFile(this, names[nr], remaining);
final int ZEROBLOCKSIZE = (int) Math.min(remaining, 32*1024);
byte[] zeros = new byte[ZEROBLOCKSIZE];
while (remaining > 0) {
int size = (int) Math.min(remaining, ZEROBLOCKSIZE);
rafs[nr].write(zeros, 0, size);
remaining -= size;
}
int i;
for (i = 0; i < lengths[nr]/ZEROBLOCKSIZE; i++)
{
rafs[nr].write(zeros);
if (listener != null)
listener.storageAllocated(this, ZEROBLOCKSIZE);
}
int size = (int)(lengths[nr] - i*ZEROBLOCKSIZE);
rafs[nr].write(zeros, 0, size);
// caller will close rafs[nr]
if (listener != null)
listener.storageAllocated(this, size);
listener.storageAllocated(this, lengths[nr]);
}
@ -868,7 +849,7 @@ public class Storage
}
// Early typecast, avoid possibly overflowing a temp integer
long start = (long) piece * (long) metainfo.getPieceLength(0);
long start = (long) piece * (long) piece_size;
int i = 0;
long raflen = lengths[i];
while (start > raflen)
@ -935,10 +916,24 @@ public class Storage
return true;
}
/**
* This is a dup of MetaInfo.getPieceLength() but we need it
* before the MetaInfo is created in our second constructor.
* @since 0.8.5
*/
private int getPieceLength(int piece) {
if (piece >= 0 && piece < pieces -1)
return piece_size;
else if (piece == pieces -1)
return (int)(total_length - ((long)piece * piece_size));
else
throw new IndexOutOfBoundsException("no piece: " + piece);
}
private int getUncheckedPiece(int piece, byte[] bs)
throws IOException
{
return getUncheckedPiece(piece, bs, 0, metainfo.getPieceLength(piece));
return getUncheckedPiece(piece, bs, 0, getPieceLength(piece));
}
private int getUncheckedPiece(int piece, byte[] bs, int off, int length)
@ -947,7 +942,7 @@ public class Storage
// XXX - copy/paste code from putPiece().
// Early typecast, avoid possibly overflowing a temp integer
long start = ((long) piece * (long) metainfo.getPieceLength(0)) + off;
long start = ((long) piece * (long) piece_size) + off;
int i = 0;
long raflen = lengths[i];

View File

@ -60,22 +60,30 @@ public class BDecoder
private int indicator = 0;
// Used for ugly hack to get SHA hash over the metainfo info map
private String special_map = "info";
private final String special_map = "info";
private boolean in_special_map = false;
private final MessageDigest sha_digest;
/** creation deferred until we encounter the special map, to make processing of announce replies more efficient */
private MessageDigest sha_digest;
// Ugly hack. Return the SHA has over bytes that make up the special map.
/**
* Ugly hack. Return the SHA has over bytes that make up the special map.
* @return null if there was no special map
*/
public byte[] get_special_map_digest()
{
if (sha_digest == null)
return null;
byte[] result = sha_digest.digest();
return result;
}
/****
// Ugly hack. Name defaults to "info".
public void set_special_map_name(String name)
{
special_map = name;
}
****/
/**
* Initalizes a new BDecoder. Nothing is read from the given
@ -84,15 +92,6 @@ public class BDecoder
public BDecoder(InputStream in)
{
this.in = in;
// XXX - Used for ugly hack.
try
{
sha_digest = MessageDigest.getInstance("SHA");
}
catch(NoSuchAlgorithmException nsa)
{
throw new InternalError(nsa.toString());
}
}
/**
@ -112,6 +111,24 @@ public class BDecoder
return new BDecoder(in).bdecode();
}
/**
* Used for SHA1 hack
* @since 0.8.5
*/
private void createDigest() {
if (sha_digest == null) {
try {
sha_digest = MessageDigest.getInstance("SHA");
} catch(NoSuchAlgorithmException nsa) {
throw new InternalError(nsa.toString());
}
} else {
// there are two info maps, but not one inside the other,
// the resulting hash will be incorrect
// throw something? - no, the check in the MetaInfo constructor will catch it.
}
}
/**
* Returns what the next bencoded object will be on the stream or -1
* when the end of stream has been reached. Can return something
@ -294,9 +311,13 @@ public class BDecoder
String key = bdecode().getString();
// XXX ugly hack
boolean special = special_map.equals(key);
if (special)
// This will not screw up if an info map contains an info map,
// but it will if there are two info maps (not one inside the other)
boolean special = (!in_special_map) && special_map.equals(key);
if (special) {
createDigest();
in_special_map = true;
}
BEValue value = bdecode();
result.put(key, value);

View File

@ -33,7 +33,6 @@ import net.i2p.data.DataHelper;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream;
import org.klomp.snark.I2PSnarkUtil;
import org.klomp.snark.MetaInfo;
@ -208,8 +207,11 @@ public class I2PSnarkServlet extends Default {
out.write("</title>\n");
// we want it to go to the base URI so we don't refresh with some funky action= value
if (!isConfigure)
out.write("<meta http-equiv=\"refresh\" content=\"60;/i2psnark/" + peerString + "\">\n");
if (!isConfigure) {
int delay = _manager.getRefreshDelaySeconds();
if (delay > 0)
out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
}
out.write(HEADER_A + _themePath + HEADER_B);
out.write("</head><body>");
out.write("<center>");
@ -351,7 +353,8 @@ public class I2PSnarkServlet extends Default {
// Using a unique name fixes Opera, except for the buttons with js confirms, see below
String ua = req.getHeader("User-Agent");
boolean isDegraded = ua != null && (ua.startsWith("Lynx") || ua.startsWith("w3m") ||
ua.startsWith("ELinks") || ua.startsWith("Dillo"));
ua.startsWith("ELinks") || ua.startsWith("Links") ||
ua.startsWith("Dillo"));
boolean noThinsp = isDegraded || (ua != null && ua.startsWith("Opera"));
if (_manager.util().connected()) {
@ -610,6 +613,7 @@ public class I2PSnarkServlet extends Default {
}
} else if ("Save".equals(action)) {
String dataDir = req.getParameter("dataDir");
boolean filesPublic = req.getParameter("filesPublic") != null;
boolean autoStart = req.getParameter("autoStart") != null;
String seedPct = req.getParameter("seedPct");
String eepHost = req.getParameter("eepHost");
@ -619,11 +623,14 @@ public class I2PSnarkServlet extends Default {
String i2cpOpts = buildI2CPOpts(req);
String upLimit = req.getParameter("upLimit");
String upBW = req.getParameter("upBW");
String refreshDel = req.getParameter("refreshDelay");
String startupDel = req.getParameter("startupDelay");
boolean useOpenTrackers = req.getParameter("useOpenTrackers") != null;
String openTrackers = req.getParameter("openTrackers");
String theme = req.getParameter("theme");
_manager.updateConfig(dataDir, autoStart, startupDel, seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts, upLimit, upBW, useOpenTrackers, openTrackers, theme);
_manager.updateConfig(dataDir, filesPublic, autoStart, refreshDel, startupDel,
seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts,
upLimit, upBW, useOpenTrackers, openTrackers, theme);
} else if ("Create".equals(action)) {
String baseData = req.getParameter("baseFile");
if (baseData != null && baseData.trim().length() > 0) {
@ -643,7 +650,6 @@ public class I2PSnarkServlet extends Default {
// This may take a long time to check the storage, but since it already exists,
// it shouldn't be THAT bad, so keep it in this thread.
Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
s.create();
s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
MetaInfo info = s.getMetaInfo();
File torrentFile = new File(_manager.getDataDir(), s.getBaseName() + ".torrent");
@ -765,8 +771,7 @@ public class I2PSnarkServlet extends Default {
}
}
long total = snark.getTotalLength();
// Early typecast, avoid possibly overflowing a temp integer
long remaining = (long) snark.getNeeded() * (long) snark.getPieceLength(0);
long remaining = snark.getRemainingLength();
if (remaining > total)
remaining = total;
long downBps = snark.getDownloadRate();
@ -978,7 +983,7 @@ public class I2PSnarkServlet extends Default {
if (noThinsp)
out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"Remove_" + b64 + "\" title=\"");
out.write("<input type=\"image\" name=\"action_Remove_" + b64 + "\" value=\"foo\" title=\"");
out.write(_("Remove the torrent from the active list, deleting the .torrent file"));
out.write("\" onclick=\"if (!confirm('");
// Can't figure out how to escape double quotes inside the onclick string.
@ -1038,6 +1043,8 @@ public class I2PSnarkServlet extends Default {
client = "Robert";
else if (ch.startsWith("LV")) // LVCS 1.0.2?; LVRS 1.0.4
client = "Transmission";
else if ("LUtU".equals(ch))
client = "KTorrent";
else
client = _("Unknown") + " (" + ch + ')';
out.write(client + "&nbsp;&nbsp;<tt>" + peer.toString().substring(5, 9)+ "</tt>");
@ -1189,7 +1196,7 @@ public class I2PSnarkServlet extends Default {
out.write("</span><hr>\n<table border=\"0\"><tr><td>");
out.write(_("From URL"));
out.write(":<td><input type=\"text\" name=\"newURL\" size=\"85\" value=\"" + newURL + "\"");
out.write("title=\"");
out.write(" title=\"");
out.write(_("Enter the torrent file download URL (I2P only), magnet link, or maggot link"));
out.write("\"> \n");
// not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
@ -1258,44 +1265,55 @@ public class I2PSnarkServlet extends Default {
out.write("&nbsp;<input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
"title=\"");
out.write(_("Specify custom tracker announce URL"));
out.write("\" > ");
out.write("<input type=\"submit\" value=\"");
out.write("\" > " +
"<input type=\"submit\" value=\"");
out.write(_("Create torrent"));
out.write("\" name=\"foo\" ></table>\n");
out.write("</form></div></div>");
out.write("\" name=\"foo\" ></table>\n" +
"</form></div></div>");
}
private static final int[] times = { 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
String dataDir = _manager.getDataDir().getAbsolutePath();
boolean filesPublic = _manager.areFilesPublic();
boolean autoStart = _manager.shouldAutoStart();
boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers();
String openTrackers = _manager.util().getOpenTrackerString();
//int seedPct = 0;
out.write("<form action=\"/i2psnark/configure\" method=\"POST\">\n");
out.write("<div class=\"configsectionpanel\"><div class=\"snarkConfig\">\n");
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("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
out.write("<form action=\"/i2psnark/configure\" method=\"POST\">\n" +
"<div class=\"configsectionpanel\"><div class=\"snarkConfig\">\n" +
"<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n" +
"<input type=\"hidden\" name=\"action\" value=\"Save\" >\n" +
"<span class=\"snarkConfigTitle\">" +
"<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
out.write(_("Configuration"));
out.write("</span><hr>\n");
out.write("<table border=\"0\"><tr><td>");
out.write("</span><hr>\n" +
"<table border=\"0\"><tr><td>");
out.write(_("Data directory"));
out.write(": <td><code>" + dataDir + "</code> <i>(");
out.write(_("Edit i2psnark.config and restart to change"));
out.write(")</i><br>\n");
out.write(")</i><br>\n" +
out.write("<tr><td>");
"<tr><td>");
out.write(_("Files readable by all"));
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"filesPublic\" value=\"true\" "
+ (filesPublic ? "checked " : "")
+ "title=\"");
out.write(_("If checked, other users may access the downloaded files"));
out.write("\" >" +
"<tr><td>");
out.write(_("Auto start"));
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"autoStart\" value=\"true\" "
+ (autoStart ? "checked " : "")
+ "title=\"");
out.write(_("If checked, automatically start torrents that are added"));
out.write("\" >");
out.write("\" >" +
out.write("<tr><td>");
"<tr><td>");
out.write(_("Theme"));
out.write(": <td><select name='theme'>");
String theme = _manager.getTheme();
@ -1306,9 +1324,28 @@ public class I2PSnarkServlet extends Default {
else
out.write("\n<OPTION value=\"" + themes[i] + "\">" + themes[i]);
}
out.write("</select>\n");
out.write("</select>\n" +
out.write("<tr><td>");
"<tr><td>");
out.write(_("Refresh time"));
out.write(": <td><select name=\"refreshDelay\">");
int delay = _manager.getRefreshDelaySeconds();
for (int i = 0; i < times.length; i++) {
out.write("<option value=\"");
out.write(Integer.toString(times[i]));
out.write("\"");
if (times[i] == delay)
out.write(" selected=\"true\"");
out.write(">");
if (times[i] > 0)
out.write(DataHelper.formatDuration2(times[i] * 1000));
else
out.write(_("Never"));
out.write("</option>\n");
}
out.write("</select><br>" +
"<tr><td>");
out.write(_("Startup delay"));
out.write(": <td><input name=\"startupDelay\" size=\"3\" class=\"r\" value=\"" + _manager.util().getStartupDelay() + "\"> ");
out.write(_("minutes"));
@ -1339,26 +1376,26 @@ public class I2PSnarkServlet extends Default {
out.write(": <td><input type=\"text\" name=\"upLimit\" class=\"r\" value=\""
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" > ");
out.write(_("peers"));
out.write("<br>\n");
out.write("<br>\n" +
out.write("<tr><td>");
"<tr><td>");
out.write(_("Up bandwidth limit"));
out.write(": <td><input type=\"text\" name=\"upBW\" class=\"r\" 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("</a>)</i><br>\n" +
out.write("<tr><td>");
"<tr><td>");
out.write(_("Use open trackers also"));
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"useOpenTrackers\" value=\"true\" "
+ (useOpenTrackers ? "checked " : "")
+ "title=\"");
out.write(_("If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"));
out.write("\" > ");
out.write("\" > " +
out.write("<tr><td>");
"<tr><td>");
out.write(_("Open tracker announce URLs"));
out.write(": <td><input type=\"text\" name=\"openTrackers\" value=\""
+ openTrackers + "\" size=\"50\" ><br>\n");
@ -1387,36 +1424,38 @@ public class I2PSnarkServlet extends Default {
out.write("<tr><td>");
out.write(_("I2CP host"));
out.write(": <td><input type=\"text\" name=\"i2cpHost\" value=\""
+ _manager.util().getI2CPHost() + "\" size=\"15\" > ");
+ _manager.util().getI2CPHost() + "\" size=\"15\" > " +
out.write("<tr><td>");
"<tr><td>");
out.write(_("I2CP port"));
out.write(": <td><input type=\"text\" name=\"i2cpPort\" class=\"r\" value=\"" +
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" > <br>\n");
}
options.remove(I2PSnarkUtil.PROP_MAX_BW);
// was accidentally in the I2CP options prior to 0.8.9 so it will be in old config files
options.remove(SnarkManager.PROP_OPENTRACKERS);
StringBuilder opts = new StringBuilder(64);
for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
String val = (String)entry.getValue();
for (Map.Entry<String, String> e : options.entrySet()) {
String key = e.getKey();
String val = e.getValue();
opts.append(key).append('=').append(val).append(' ');
}
out.write("<tr><td>");
out.write(_("I2CP options"));
out.write(": <td><textarea name=\"i2cpOpts\" cols=\"60\" rows=\"1\" wrap=\"off\" spellcheck=\"false\" >"
+ opts.toString() + "</textarea><br>\n");
+ opts.toString() + "</textarea><br>\n" +
out.write("<tr><td>&nbsp;<td><input type=\"submit\" value=\"");
"<tr><td>&nbsp;<td><input type=\"submit\" value=\"");
out.write(_("Save configuration"));
out.write("\" name=\"foo\" >\n");
out.write("</table></div></div></form>");
out.write("\" name=\"foo\" >\n" +
"</table></div></div></form>");
}
private void writeConfigLink(PrintWriter out) throws IOException {
out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n");
out.write("<span class=\"snarkConfigTitle\"><a href=\"configure\">");
out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n" +
"<span class=\"snarkConfigTitle\"><a href=\"configure\">" +
"<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
out.write(_("Configuration"));
out.write("</a></span></span></div>\n");
}
@ -1847,7 +1886,7 @@ public class I2PSnarkServlet extends Default {
buf.append("</TR>\n");
}
if (showSaveButton) {
buf.append("<thead><tr><th colspan=\"3\">&nbsp;</th><th align=\"center\"><input type=\"submit\" value=\"");
buf.append("<thead><tr><th colspan=\"3\">&nbsp;</th><th class=\"headerpriority\"><input type=\"submit\" value=\"");
buf.append(_("Save priorities"));
buf.append("\" name=\"foo\" ></th></tr></thead>\n");
}
@ -1968,16 +2007,15 @@ private static class FetchAndAdd implements Runnable {
FileInputStream in = null;
try {
in = new FileInputStream(file);
// we do not retain this MetaInfo object, hopefully it will go away quickly
MetaInfo info = new MetaInfo(in);
byte[] fileInfoHash = new byte[20];
String name = MetaInfo.getNameAndInfoHash(in, fileInfoHash);
try { in.close(); } catch (IOException ioe) {}
Snark snark = _manager.getTorrentByInfoHash(info.getInfoHash());
Snark snark = _manager.getTorrentByInfoHash(fileInfoHash);
if (snark != null) {
_manager.addMessage(_("Torrent with this info hash is already running: {0}", snark.getBaseName()));
return;
}
String name = info.getName();
name = Storage.filterName(name);
name = name + ".torrent";
File torrentFile = new File(_manager.getDataDir(), name);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,951 @@
# 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
#
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-09-23 19:47+0000\n"
"PO-Revision-Date: 2011-06-11 09:17+0000\n"
"Last-Translator: duck <duck@mail.i2p>\n"
"Language-Team: Italian (http://www.transifex.net/projects/p/I2P/team/it/)\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:355
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:357
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:369
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:371
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:383
#, java-format
msgid "Startup delay changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:394
#, java-format
msgid "Refresh time changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:396
msgid "Refresh disabled"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:451
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:455
#, java-format
msgid "I2CP options changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:460
msgid "Disconnecting old I2CP destination"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:462
#, java-format
msgid "I2CP settings changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:467
msgid ""
"Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:471
msgid "Unable to reconnect with the old settings!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:473
msgid "Reconnected on the new I2CP destination"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:480
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:492
msgid "New files will be publicly readable"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:494
msgid "New files will not be publicly readable"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:501
msgid "Enabled autostart"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:503
msgid "Disabled autostart"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:509
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:511
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:519
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:526
#, java-format
msgid "{0} theme loaded, return to main i2psnark page to view."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:533
msgid "Configuration unchanged."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:543
#, java-format
msgid "Unable to save the config to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:608
msgid "Connecting to I2P"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:611
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:620
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr ""
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:642
#, java-format
msgid "Cannot open \"{0}\""
msgstr ""
#. TODO - if the existing one is a magnet, delete it and add the metainfo instead?
#: ../java/src/org/klomp/snark/SnarkManager.java:661
#: ../java/src/org/klomp/snark/SnarkManager.java:737
#: ../java/src/org/klomp/snark/SnarkManager.java:792
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2015
#, java-format
msgid "Torrent with this info hash is already running: {0}"
msgstr ""
#. addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:668
#, java-format
msgid ""
"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers "
"only."
msgstr ""
#. addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:673
#, java-format
msgid ""
"Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is "
"enabled before starting this torrent."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:694
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:699
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2037
#, java-format
msgid "ERROR - Out of memory, cannot create torrent from {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:711
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:713
#, java-format
msgid "Torrent added: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:748
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493
#, java-format
msgid "Fetching {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:751
#, java-format
msgid ""
"We have no saved peers and no other torrents are running. Fetch of {0} will "
"not succeed until you start another torrent."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:755
#, java-format
msgid "Adding {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:802
#: ../java/src/org/klomp/snark/SnarkManager.java:825
#: ../java/src/org/klomp/snark/SnarkManager.java:1260
#, java-format
msgid "Failed to copy torrent file to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1052
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1054
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1056
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1058
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1060
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1061
#, java-format
msgid "Limit is {0}B"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1063
#, java-format
msgid "Torrent \"{0}\" has no data, deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1071
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1087
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1108
#: ../java/src/org/klomp/snark/SnarkManager.java:1126
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1147
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1155
#, java-format
msgid "Adding torrents in {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1208
#, java-format
msgid "Download finished: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1256
#, java-format
msgid "Metainfo received for {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1257
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:528
#, java-format
msgid "Starting up torrent {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1313
msgid "Unable to connect to I2P!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1319
#, java-format
msgid "Unable to add {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:204
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:220
msgid "Torrents"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:223
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:230
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1033
msgid "I2PSnark"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:227
msgid "Refresh page"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:232
msgid "Forum"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:286
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758
msgid "Status"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:292
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294
msgid "Hide Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:299
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:301
msgid "Show Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1682
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1698
msgid "Torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:312
msgid "Estimated time remaining"
msgstr ""
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315
msgid "ETA"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319
msgid "Downloaded"
msgstr ""
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:322
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:336
msgid "RX"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:326
msgid "Uploaded"
msgstr ""
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:329
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
msgid "TX"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:334
msgid "Down Rate"
msgstr ""
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:339
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:348
msgid "Rate"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:344
msgid "Up Rate"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:368
msgid "Stop all torrents and the I2P tunnel"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:370
msgid "Stop All"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:379
msgid "Start all torrents and the I2P tunnel"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:381
msgid "Start All"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400
msgid "No torrents loaded."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405
msgid "Totals"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] ""
msgstr[1] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:410
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] ""
msgstr[1] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:499
#, java-format
msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:547
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:574
#, java-format
msgid "Magnet deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:580
#, java-format
msgid "Torrent file deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:596
#, java-format
msgid "Data file deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:588
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:607
#, java-format
msgid "Data dir deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:644
msgid "Error creating torrent - you must select a tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:659
#, java-format
msgid "Torrent created for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:661
#, 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:663
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:669
msgid "Error creating torrent - you must enter a file or directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:672
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683
msgid "I2P tunnel closed."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:686
msgid "Opening the I2P tunnel and starting all torrents."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:813
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:819
msgid "Tracker Error"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:811
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:815
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:827
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:831
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:843
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:852
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] ""
msgstr[1] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:824
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829
msgid "Seeding"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:833
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1704
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809
msgid "Complete"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:841
msgid "OK"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:845
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:850
msgid "Stalled"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:857
msgid "No Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:859
msgid "Stopped"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:891
msgid "Torrent details"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:903
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1167
msgid "Info"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:918
msgid "View files"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:920
msgid "Open file"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962
msgid "Stop the torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:964
msgid "Stop"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974
msgid "Start the torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:976
msgid "Start"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr ""
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:992
#, java-format
msgid ""
"Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded "
"data will not be deleted) ?"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:995
msgid "Remove"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
msgid "Delete the .torrent file and the associated data file(s)"
msgstr ""
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1011
#, java-format
msgid ""
"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded "
"data?"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1014
msgid "Delete"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1049
msgid "Unknown"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061
msgid "Seed"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1084
msgid "Uninteresting (The peer has no pieces we need)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1106
msgid "Uninterested (We have no pieces the peer needs)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1108
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1166
#, java-format
msgid "Details at {0} tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1195
msgid "Add Torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1197
msgid "From URL"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1200
msgid ""
"Enter the torrent file download URL (I2P only), magnet link, or maggot link"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1205
msgid "Add torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1208
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210
msgid "Removing a .torrent will cause it to stop."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233
msgid "Create Torrent"
msgstr ""
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1236
msgid "Data to seed"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240
msgid "File or directory to seed (must be within the specified path)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1242
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1723
msgid "Tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244
msgid "Select a tracker"
msgstr ""
#. out.write(_("Open trackers and DHT only"));
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1249
msgid "Open trackers only"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1264
msgid "or"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267
msgid "Specify custom tracker announce URL"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270
msgid "Create torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459
msgid "Configuration"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295
msgid "Data directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297
msgid "Edit i2psnark.config and restart to change"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301
msgid "Files readable by all"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305
msgid "If checked, other users may access the downloaded files"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1309
msgid "Auto start"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1313
msgid "If checked, automatically start torrents that are added"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1317
msgid "Theme"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1330
msgid "Refresh time"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1343
msgid "Never"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1349
msgid "Startup delay"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1351
msgid "minutes"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1375
msgid "Total uploader limit"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1378
msgid "peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1382
msgid "Up bandwidth limit"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1385
msgid "Half available bandwidth recommended."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1387
msgid "View or change router bandwidth"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1391
msgid "Use open trackers also"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1395
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:1399
msgid "Open tracker announce URLs"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411
msgid "Inbound Settings"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1417
msgid "Outbound Settings"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425
msgid "I2CP host"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430
msgid "I2CP port"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1445
msgid "I2CP options"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450
msgid "Save configuration"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1475
#, java-format
msgid "Invalid magnet URL {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1509
#, java-format
msgid "Invalid info hash in magnet URL {0}"
msgstr ""
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] ""
msgstr[1] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1540
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] ""
msgstr[1] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1702
msgid "Completion"
msgstr ""
#. else unknown
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1706
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1755
msgid "Size"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1711
msgid "Files"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713
msgid "Pieces"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714
msgid "Piece size"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736
msgid "Magnet link"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1753
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792
msgid "Directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1762
msgid "Priority"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1767
msgid "Up to higher level directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797
msgid "Torrent not found?"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806
msgid "File not found in torrent?"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1819
msgid "complete"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1820
msgid "bytes remaining"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845
msgid "Open"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871
msgid "High"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1876
msgid "Normal"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1881
msgid "Skip"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1890
msgid "Save priorities"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2006
#, java-format
msgid "Torrent fetched from {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2027
#, java-format
msgid "Torrent already running: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2029
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035
#, java-format
msgid "Torrent at {0} was not valid"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2042
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr ""

View File

@ -8,14 +8,14 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-20 12:17+0000\n"
"POT-Creation-Date: 2011-03-03 18:28+0000\n"
"PO-Revision-Date: 2011-02-20 12:15+0000\n"
"Last-Translator: ducki2p <ducki2p@gmail.com>\n"
"Language-Team: Dutch <>\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: nl\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:307
@ -135,7 +135,7 @@ msgstr "Kan \"{0}\" niet openen"
#: ../java/src/org/klomp/snark/SnarkManager.java:586
#: ../java/src/org/klomp/snark/SnarkManager.java:661
#: ../java/src/org/klomp/snark/SnarkManager.java:716
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1976
#, java-format
msgid "Torrent with this info hash is already running: {0}"
msgstr "Torrent met deze info hash is al actief: {0}"
@ -166,7 +166,7 @@ msgid "Torrent in \"{0}\" is invalid"
msgstr "Torrent in \"{0}\" is ongeldig"
#: ../java/src/org/klomp/snark/SnarkManager.java:624
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1994
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1999
#, java-format
msgid "ERROR - Out of memory, cannot create torrent from {0}"
msgstr "ERROR - Geen geheugen meer, kan geen torrent maken van {0}"
@ -182,7 +182,7 @@ msgid "Torrent added: \"{0}\""
msgstr "Torrent toegevoegd: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:672
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:489
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:490
#, java-format
msgid "Fetching {0}"
msgstr "Downloaden {0}"
@ -277,7 +277,7 @@ msgid "Metainfo received for {0}"
msgstr "Metainfo ontvangen voor {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1171
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:525
#, java-format
msgid "Starting up torrent {0}"
msgstr "Starten met torrent {0}"
@ -301,7 +301,7 @@ msgstr "Torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:221
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:228
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1024
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1028
msgid "I2PSnark"
msgstr "I2PSnark"
@ -314,7 +314,7 @@ msgid "Forum"
msgstr "Forum"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1715
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1719
msgid "Status"
msgstr "Status"
@ -329,8 +329,8 @@ msgid "Show Peers"
msgstr "Toon Peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:306
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1639
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1655
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1659
msgid "Torrent"
msgstr "Torrent"
@ -377,88 +377,88 @@ msgstr "Rato"
msgid "Up Rate"
msgstr "Up Snelheid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:364
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:365
msgid "Stop all torrents and the I2P tunnel"
msgstr "Stop alle torrents en de I2P tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:366
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:367
msgid "Stop All"
msgstr "Stop Alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:375
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:376
msgid "Start all torrents and the I2P tunnel"
msgstr "Start alle torrents en de I2P tunnel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:378
msgid "Start All"
msgstr "Start Alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:397
msgid "No torrents loaded."
msgstr "Geen torrents geladen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:401
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:402
msgid "Totals"
msgstr "Totalen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:403
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:404
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "1 torrent"
msgstr[1] "{0} torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:406
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "1 verbonden peer"
msgstr[1] "{0} verbonden peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496
#, java-format
msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\""
msgstr "Ongeldige URL: moet beginnen met \"http://\", \"{0}\", of \"{1}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:543
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:544
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571
#, java-format
msgid "Magnet deleted: {0}"
msgstr "Magnet verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:551
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:576
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:552
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:577
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Torrent bestand verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:582
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:592
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:593
#, java-format
msgid "Data file deleted: {0}"
msgstr "Data bestand verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:584
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:594
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:595
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Kan data bestand niet verwijderen: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:603
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Data directory verwijderd: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:636
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:637
msgid "Error creating torrent - you must select a tracker"
msgstr "Fout bij maken van torrent - je moet een tracker selecteren"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:652
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:653
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Torrent gemaakt voor \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:654
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:655
#, java-format
msgid ""
"Many I2P trackers require you to register new torrents before seeding - "
@ -467,117 +467,117 @@ msgstr ""
"Veel I2P trackers vereisen dat je de nieuwe torrent registreert voor het "
"seeden - doe dit voordat je \"{0}\" start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:656
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Fout bij het maken van een torrent voor \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:659
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Kan geen torrent maken voor niet-bestaande data: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:662
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:663
msgid "Error creating torrent - you must enter a file or directory"
msgstr ""
"Fout bij het maken van de torrent - je moet een bestand of directory invullen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Stoppen van alle torrents en sluiten van I2P tunnel."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:677
msgid "I2P tunnel closed."
msgstr "I2P tunnel gesloten."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:679
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Openen van de I2P tunnel en starten van alle torrents."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:802
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:807
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:813
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:803
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814
msgid "Tracker Error"
msgstr "Tracker Fout"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:809
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:833
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:842
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:846
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:806
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:822
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:834
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:838
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:843
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:847
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "1 peer"
msgstr[1] "{0} peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:818
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:819
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:824
msgid "Seeding"
msgstr "Seeding"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:827
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1661
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1766
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1770
msgid "Complete"
msgstr "Voltooid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:830
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:831
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
msgid "OK"
msgstr "OK"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:844
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:840
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:845
msgid "Stalled"
msgstr "Vastgelopen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:851
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:849
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:852
msgid "No Peers"
msgstr "Geen Peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:853
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854
msgid "Stopped"
msgstr "Gestopt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:885
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:886
msgid "Torrent details"
msgstr "Torrent details"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:897
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1156
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:898
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1160
msgid "Info"
msgstr "Info"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:912
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:913
msgid "View files"
msgstr "Bekijk bestanden"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:914
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:915
msgid "Open file"
msgstr "Open bestand"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:956
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:957
msgid "Stop the torrent"
msgstr "Stop de torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:959
msgid "Stop"
msgstr "Stop"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:967
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
msgid "Start the torrent"
msgstr "Start de torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:971
msgid "Start"
msgstr "Start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr ""
"Verwijder de torrent van de actieve lijst, het .torrent bestand wordt "
@ -586,7 +586,7 @@ msgstr ""
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:984
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
#, java-format
msgid ""
"Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded "
@ -595,18 +595,18 @@ msgstr ""
"Weet je zeker dat je het bestand \\''{0}.torrent\\'' wilt verwijderen "
"(gedownloade data zal niet worden verwijderd) ?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:990
msgid "Remove"
msgstr "Weghalen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:997
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Verwijder het .torrent bestand en de gerelateerde data bestand(en)"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1002
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
#, java-format
msgid ""
"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded "
@ -615,163 +615,163 @@ msgstr ""
"Weet je zeker dat je de torrent \\''{0}\\'' en alle gedownloade data wilt "
"verwijderen?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1005
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1009
msgid "Delete"
msgstr "Verwijderen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1038
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042
msgid "Unknown"
msgstr "Onbekend"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1050
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054
msgid "Seed"
msgstr "Seed"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1073
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "Niet interessant (De peer heeft geen stukken die we nodig hebben)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1075
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1079
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "Verstikt (De peer laat ons niet toe om stukken op te vragen)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1095
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1099
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "Niet geïnteresseerd (We heben geen stukken die de peer nodig heeft)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1097
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1101
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Verstikt (We laten de peer niet toe om stukken op te vragen)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1155
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1159
#, java-format
msgid "Details at {0} tracker"
msgstr "Details op de {0} tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1184
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1188
msgid "Add Torrent"
msgstr "Torrent Toevoegen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1186
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190
msgid "From URL"
msgstr "Van URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1189
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1193
msgid ""
"Enter the torrent file download URL (I2P only), magnet link, or maggot link"
msgstr "Geef de torrent download URL (alleen I2P), magnet link, of maggot link"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1194
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1198
msgid "Add torrent"
msgstr "Torrent toevoegen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1197
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1201
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr "Je kan ook .torrent bestanden kopieren naar: {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1199
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1203
msgid "Removing a .torrent will cause it to stop."
msgstr "Verwijderen van een .torrent zorgt dat deze stopt."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1222
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226
msgid "Create Torrent"
msgstr "Creëer Torrent"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1225
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229
msgid "Data to seed"
msgstr "Data om te seeden"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233
msgid "File or directory to seed (must be within the specified path)"
msgstr ""
"Bestand of directory om te seeden (moet binnen het gespecificeerde pad zijn)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684
msgid "Tracker"
msgstr "Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
msgid "Select a tracker"
msgstr "Selecteer een tracker"
#. out.write(_("Open trackers and DHT only"));
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1238
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1242
msgid "Open trackers only"
msgstr "Alleen Open trackers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1257
msgid "or"
msgstr "of"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1260
msgid "Specify custom tracker announce URL"
msgstr "Specificeer aangepaste tracker aankondigings URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263
msgid "Create torrent"
msgstr "Creëer torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1420
msgid "Configuration"
msgstr "Configuratie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1285
msgid "Data directory"
msgstr "Data directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287
msgid "Edit i2psnark.config and restart to change"
msgstr "Bewerk i2psnark.config en herstart de wijziging"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
msgid "Auto start"
msgstr "Auto start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295
msgid "If checked, automatically start torrents that are added"
msgstr "Indien aangevinkt, start toegevoegde torrents automatisch"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1299
msgid "Theme"
msgstr "Thema"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1308
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1312
msgid "Startup delay"
msgstr "Startup vertraging"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1314
msgid "minutes"
msgstr "minuten"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1334
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338
msgid "Total uploader limit"
msgstr "Totale uploader limiet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1337
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1341
msgid "peers"
msgstr "peers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1341
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1345
msgid "Up bandwidth limit"
msgstr "Up bandbreedte limiet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1344
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1348
msgid "Half available bandwidth recommended."
msgstr "Helft van beschikbare bandbreedte aanbevolen."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1346
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1350
msgid "View or change router bandwidth"
msgstr "Bekijk of wijzig router bandbreedte"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1350
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1354
msgid "Use open trackers also"
msgstr "Gebruik ook open trackers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1354
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358
msgid ""
"If checked, announce torrents to open trackers as well as the tracker listed "
"in the torrent file"
@ -779,155 +779,155 @@ msgstr ""
"Indien aangevinkt, kondig torrents ook aan bij de tracker uit het torrent "
"bestand"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1362
msgid "Open tracker announce URLs"
msgstr "Open tracker aankondigings URLs"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1374
msgid "Inbound Settings"
msgstr "Inkomende Instellingen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1376
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1380
msgid "Outbound Settings"
msgstr "Uitgaande Instellingen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1384
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1388
msgid "I2CP host"
msgstr "I2CP host"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1389
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1393
msgid "I2CP port"
msgstr "I2CP poort"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1406
msgid "I2CP options"
msgstr "I2CP opties"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1407
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411
msgid "Save configuration"
msgstr "Configuratie opslaan"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1432
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1436
#, java-format
msgid "Invalid magnet URL {0}"
msgstr "Ongeldige magnet URL {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1466
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1470
#, java-format
msgid "Invalid info hash in magnet URL {0}"
msgstr "Ongeldige info hash in magnet URL {0}"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1496
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1500
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "1 hop"
msgstr[1] "{0} hops"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1497
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1501
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "1 tunnel"
msgstr[1] "{0} tunnels"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1659
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1663
msgid "Completion"
msgstr "Voltooiing"
#. else unknown
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1663
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1667
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716
msgid "Size"
msgstr "Grootte"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1668
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1672
msgid "Files"
msgstr "Bestanden"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1670
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1674
msgid "Pieces"
msgstr "Stukken"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1671
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675
msgid "Piece size"
msgstr "Stukgrootte"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1693
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697
msgid "Magnet link"
msgstr "Magnet link"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1710
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1753
msgid "Directory"
msgstr "Directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1719
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1723
msgid "Priority"
msgstr "Prioriteit"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1728
msgid "Up to higher level directory"
msgstr "Naar bovenliggende directory"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758
msgid "Torrent not found?"
msgstr "Torrent niet gevonden?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1763
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1767
msgid "File not found in torrent?"
msgstr "Bestand niet gevonden in torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1776
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780
msgid "complete"
msgstr "voltooid"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1777
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1781
msgid "bytes remaining"
msgstr "bytes resterend"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1802
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806
msgid "Open"
msgstr "Open"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1828
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1832
msgid "High"
msgstr "Hoog"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1833
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1837
msgid "Normal"
msgstr "Normaal"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842
msgid "Skip"
msgstr "Overslaan"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851
msgid "Save priorities"
msgstr "Prioriteiten opslaan"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1962
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1967
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent gedownload van {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1989
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent draait al: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1991
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent zit al in de wachtrij: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1992
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Torrent op {0} was niet geldig"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1999
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2004
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Torrent was niet ontvangen van {0}"

View File

@ -0,0 +1,941 @@
# 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.
# <b790979@klzlk.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-06-11 08:22+0000\n"
"PO-Revision-Date: 2011-06-26 15:17+0000\n"
"Last-Translator: PolishAnon <b790979@klzlk.com>\n"
"Language-Team: Polish (http://www.transifex.net/projects/p/I2P/team/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pl\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:307
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Ograniczenie liczby uploaderów zmieniono do {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:309
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "Minimalny całkowity limit uploadera: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:321
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Ograniczenie pasma WY zmieniono na: {0} KB/s"
#: ../java/src/org/klomp/snark/SnarkManager.java:323
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "Minimalne pasmo WY to: {0} KB/s"
#: ../java/src/org/klomp/snark/SnarkManager.java:335
#, java-format
msgid "Startup delay changed to {0}"
msgstr "Opóźnienia startu zmieniono na {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:386
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr ""
"Zmiany dotyczące I2CP i tuneli będą wprowadzone po zatrzymaniu wszystkich "
"torrentów."
#: ../java/src/org/klomp/snark/SnarkManager.java:393
msgid "Disconnecting old I2CP destination"
msgstr "Rozłączanie starych celów I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:397
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "Ustawienia I2CP zmienione do: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:402
msgid ""
"Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr ""
"Nie można połączyć się z nowymi ustawieniami, powrót do starych ustawień "
"I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:406
msgid "Unable to reconnect with the old settings!"
msgstr "Nie można się połączyć ze starymi ustawieniami!"
#: ../java/src/org/klomp/snark/SnarkManager.java:408
msgid "Reconnected on the new I2CP destination"
msgstr "Ponowne podłączanie do nowych celów I2CP"
#: ../java/src/org/klomp/snark/SnarkManager.java:418
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "Nasłuch I2CP zrestartowany dla \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:429
msgid "Enabled autostart"
msgstr "Włącz automatycznie uruchamianie"
#: ../java/src/org/klomp/snark/SnarkManager.java:431
msgid "Disabled autostart"
msgstr "Wyłącz automatycznie uruchamianie"
#: ../java/src/org/klomp/snark/SnarkManager.java:437
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr "Włączono otwarte trackery - wymagane ponowne uruchomienie torrenta."
#: ../java/src/org/klomp/snark/SnarkManager.java:439
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr "Wyłączono otwarte trackery - wymagane ponowne uruchomienie torrenta."
#: ../java/src/org/klomp/snark/SnarkManager.java:447
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr ""
"Zmieniła się lista otwartych trackerów - wymagane ponowne uruchomienie "
"torrenta."
#: ../java/src/org/klomp/snark/SnarkManager.java:454
#, java-format
msgid "{0} theme loaded, return to main i2psnark page to view."
msgstr "{0} temat załadowany, powrót do strony głównej i2psnark by zobaczyć."
#: ../java/src/org/klomp/snark/SnarkManager.java:461
msgid "Configuration unchanged."
msgstr "Ustawienia niezmienione."
#: ../java/src/org/klomp/snark/SnarkManager.java:471
#, java-format
msgid "Unable to save the config to {0}"
msgstr "Nie można zapisać konfiguracji do {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:536
msgid "Connecting to I2P"
msgstr "Łączenie z I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:539
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Nie można się połączyć z I2P, sprawdź swoje ustawienia I2CP!"
#: ../java/src/org/klomp/snark/SnarkManager.java:548
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Błąd: Nie można dodać torrenta {0}"
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:570
#, java-format
msgid "Cannot open \"{0}\""
msgstr "Nie można otworzyć \"{0}\""
#. TODO - if the existing one is a magnet, delete it and add the metainfo
#. instead?
#: ../java/src/org/klomp/snark/SnarkManager.java:589
#: ../java/src/org/klomp/snark/SnarkManager.java:665
#: ../java/src/org/klomp/snark/SnarkManager.java:720
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1976
#, java-format
msgid "Torrent with this info hash is already running: {0}"
msgstr ""
#. addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P
#. open trackers and DHT only.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:596
#, java-format
msgid ""
"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers "
"only."
msgstr ""
#. addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open
#. trackers are disabled, you should enable open trackers or DHT before
#. starting the torrent.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:601
#, java-format
msgid ""
"Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is "
"enabled before starting this torrent."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:622
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "Torrent w \"{0}\" jest niepoprawny"
#: ../java/src/org/klomp/snark/SnarkManager.java:627
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1998
#, java-format
msgid "ERROR - Out of memory, cannot create torrent from {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:639
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Torrent dodany i uruchomiony: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:641
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Torrent dodany: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:676
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:491
#, java-format
msgid "Fetching {0}"
msgstr "Pobieranie: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:679
#, java-format
msgid ""
"We have no saved peers and no other torrents are running. Fetch of {0} will "
"not succeed until you start another torrent."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:683
#, java-format
msgid "Adding {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:730
#: ../java/src/org/klomp/snark/SnarkManager.java:753
#: ../java/src/org/klomp/snark/SnarkManager.java:1180
#, java-format
msgid "Failed to copy torrent file to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:976
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "Za dużo plików w \"{0}\" ({1}), usuwanie go!"
#: ../java/src/org/klomp/snark/SnarkManager.java:978
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "Torrent \"{0}\" nie może się kończyć w \".torrent\", usuwanie go!"
#: ../java/src/org/klomp/snark/SnarkManager.java:980
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "W torrencie \"{0}\" nie ma piece'ów, usuwanie go!"
#: ../java/src/org/klomp/snark/SnarkManager.java:982
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "Za dużo piece''ów w \"{0}\" (limit to {1}), usuwanie go!"
#: ../java/src/org/klomp/snark/SnarkManager.java:984
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "Za duże piece''y w torrencie \"{0}\" ({1}B), usuwanie go."
#: ../java/src/org/klomp/snark/SnarkManager.java:985
#, java-format
msgid "Limit is {0}B"
msgstr "Granica to {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:987
#, java-format
msgid "Torrent \"{0}\" has no data, deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:995
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Torrenty większe niż {0}B nie są jeszcze wspierane, usunięcie \"{1}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:1011
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Błąd: nie można usunąć torrenta {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1032
#: ../java/src/org/klomp/snark/SnarkManager.java:1050
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Torrent zatrzymany: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:1071
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Torrent usunięty: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:1079
#, java-format
msgid "Adding torrents in {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1128
#, java-format
msgid "Download finished: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1176
#, java-format
msgid "Metainfo received for {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1177
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:526
#, java-format
msgid "Starting up torrent {0}"
msgstr "Uruchamianie torrenta: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1231
msgid "Unable to connect to I2P!"
msgstr "Nie można podłączyć się do I2P!"
#: ../java/src/org/klomp/snark/SnarkManager.java:1237
#, java-format
msgid "Unable to add {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:205
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark anonimowy klient BitTorrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:218
msgid "Torrents"
msgstr "Torrenty"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:221
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:228
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1028
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:225
msgid "Refresh page"
msgstr "Odśwież stronę"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:230
msgid "Forum"
msgstr "Forum"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1719
msgid "Status"
msgstr "Status"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:290
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:292
msgid "Hide Peers"
msgstr "Ukryj peery"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:299
msgid "Show Peers"
msgstr "Pokaż peery"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:306
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1659
msgid "Torrent"
msgstr "Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:310
msgid "Estimated time remaining"
msgstr ""
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313
msgid "ETA"
msgstr "Pozostało"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:317
msgid "Downloaded"
msgstr "Pobrano"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:320
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:334
msgid "RX"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324
msgid "Uploaded"
msgstr "Wysłano"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:327
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:344
msgid "TX"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:332
msgid "Down Rate"
msgstr "Prędkość pobierania"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:337
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
msgid "Rate"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
msgid "Up Rate"
msgstr "Prędkość wysyłania"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:366
msgid "Stop all torrents and the I2P tunnel"
msgstr "Zatrzymaj wszystkie torrenty i tunel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:368
msgid "Stop All"
msgstr "Zatrzymaj wszystkie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
msgid "Start all torrents and the I2P tunnel"
msgstr "Uruchom wszystkie torrenty i tunel I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:379
msgid "Start All"
msgstr "Uruchom wszystkie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398
msgid "No torrents loaded."
msgstr "Nie załadowano torrentów."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:403
msgid "Totals"
msgstr "Łącznie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "{0} torrent"
msgstr[1] "{0} torrenty"
msgstr[2] "{0} torrentów"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:408
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "{0} podłączony peer"
msgstr[1] "{0} podłączone peery"
msgstr[2] "{0} podłączonych peerów"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:497
#, java-format
msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:545
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:572
#, java-format
msgid "Magnet deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:553
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:578
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Plik torrenta usunięto: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:584
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:594
#, java-format
msgid "Data file deleted: {0}"
msgstr "Pliki z danymi usunięte: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:596
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Nie można usunąć pliku z danymi: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:605
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Usunięto katalog z danymi: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:638
msgid "Error creating torrent - you must select a tracker"
msgstr "Błąd przy tworzeniu torrenta - musisz wybrać tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:653
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Utworzono torrent dla \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:655
#, java-format
msgid ""
"Many I2P trackers require you to register new torrents before seeding - "
"please do so before starting \"{0}\""
msgstr ""
"Wiele trackerów w I2P wymaga zarejestrowania torrenta przed seedowaniem - "
"proszę, zrób tak przed uruchomieniem \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Błąd podczas tworzenia torrenta dla: \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Nie można utworzyć torrenta dla nieistniejących danych: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:663
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Błąd przy tworzeniu torrenta - musisz podać plik lub katalog"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Zatrzymywanie wszystkich torrentów i zamykanie tunelu I2P"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:677
msgid "I2P tunnel closed."
msgstr "Zamknięto tunel I2P."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Otwieranie tunelu I2P i uruchamianie wszystkich torrentów."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:803
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814
msgid "Tracker Error"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:806
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:822
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:834
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:838
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:843
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:847
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "{0} peer"
msgstr[1] "{0} peery"
msgstr[2] "{0} peerów"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:819
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:824
msgid "Seeding"
msgstr "Seedowanie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1770
msgid "Complete"
msgstr "Zakończono"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:831
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
msgid "OK"
msgstr "OK"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:840
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:845
msgid "Stalled"
msgstr "Utknięto"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:849
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:852
msgid "No Peers"
msgstr "Brak peerów"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854
msgid "Stopped"
msgstr "Zatrzymany"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:886
msgid "Torrent details"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:898
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1160
msgid "Info"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:913
msgid "View files"
msgstr "Zobacz pliki"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:915
msgid "Open file"
msgstr "Otwórz plik"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:957
msgid "Stop the torrent"
msgstr "Zatrzymaj torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:959
msgid "Stop"
msgstr "Zatrzymaj"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
msgid "Start the torrent"
msgstr "Uruchom torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:971
msgid "Start"
msgstr "Uruchom"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Usuń torrent z aktywnej listy, usuwając plik .torrent"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
#, java-format
msgid ""
"Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded "
"data will not be deleted) ?"
msgstr ""
"Czy na pewno chcesz usunąć plik \\''{0}.torrent\\''? (pobrane dane nie "
"zostaną usunięte)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:990
msgid "Remove"
msgstr "Usuń"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Usuń plik .torrent i związane z nim pliki z danymi"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
#, java-format
msgid ""
"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded "
"data?"
msgstr "Czy na pewno chcesz usunąć plik \\''{0}.torrent\\'' oraz pobrane dane?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1009
msgid "Delete"
msgstr "Usuń"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042
msgid "Unknown"
msgstr "Nieznany"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054
msgid "Seed"
msgstr "Seed"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "Uninteresting (peer nie ma piece'ów, które potrzebujemy)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1079
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "Choked (peer nie pozwala nam na prośbę o piece)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1099
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "Uninterested (nie mamy piece'ów, których peer potrzebuje)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1101
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Choking (nie pozwalamy peerowi na prośbę o piece)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1159
#, java-format
msgid "Details at {0} tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1188
msgid "Add Torrent"
msgstr "Dodaj torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190
msgid "From URL"
msgstr "Z adresu URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1193
msgid ""
"Enter the torrent file download URL (I2P only), magnet link, or maggot link"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1198
msgid "Add torrent"
msgstr "Dodaj torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1201
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1203
msgid "Removing a .torrent will cause it to stop."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226
msgid "Create Torrent"
msgstr "Utwórz torrent"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\"
#. value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229
msgid "Data to seed"
msgstr "Dane do seedowania"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233
msgid "File or directory to seed (must be within the specified path)"
msgstr ""
"Plik lub katalog do seedowania (musi się znajdować wewnątrz podanej ścieżki)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684
msgid "Tracker"
msgstr "Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
msgid "Select a tracker"
msgstr "Wybierz tracker"
#. out.write(_("Open trackers and DHT only"));
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1242
msgid "Open trackers only"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1257
msgid "or"
msgstr "lub"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1260
msgid "Specify custom tracker announce URL"
msgstr "Podaj własny adres announce trackera"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263
msgid "Create torrent"
msgstr "Utwórz torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1420
msgid "Configuration"
msgstr "Ustawienia"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1285
msgid "Data directory"
msgstr "Katalog z danymi"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287
msgid "Edit i2psnark.config and restart to change"
msgstr ""
"Edytuj plik i2psnark.config i uruchom ponownie by zmiany weszły w życie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
msgid "Auto start"
msgstr "Automatyczne uruchamianie"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295
msgid "If checked, automatically start torrents that are added"
msgstr "Jeśli zaznaczone - automatycznie uruchamiaj dodane torrenty"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1299
msgid "Theme"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1312
msgid "Startup delay"
msgstr "Opóźnienie uruchomienia"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1314
msgid "minutes"
msgstr "minuty"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338
msgid "Total uploader limit"
msgstr "Całkowity limit uploaderów"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1341
msgid "peers"
msgstr "peery"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1345
msgid "Up bandwidth limit"
msgstr "Ograniczenie pasma WY"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1348
msgid "Half available bandwidth recommended."
msgstr "Zalecana połowa dostępnego pasma."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1350
msgid "View or change router bandwidth"
msgstr "Zobacz lub zmień pasmo routera"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1354
msgid "Use open trackers also"
msgstr "Używaj również otwartych trackerów"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358
msgid ""
"If checked, announce torrents to open trackers as well as the tracker listed"
" in the torrent file"
msgstr ""
"Jeśli zaznaczone, zgłaszaj torrenty do otwartych trackerów, jak również do "
"trackerów podanych w pliku torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1362
msgid "Open tracker announce URLs"
msgstr "URL otwartego trackera"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1374
msgid "Inbound Settings"
msgstr "Tunele wejściowe"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1380
msgid "Outbound Settings"
msgstr "Tunele wyjściowe"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1388
msgid "I2CP host"
msgstr "Adres I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1393
msgid "I2CP port"
msgstr "Port I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1406
msgid "I2CP options"
msgstr "Parametry I2CP"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411
msgid "Save configuration"
msgstr "Zapisz ustawienia"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1436
#, java-format
msgid "Invalid magnet URL {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1470
#, java-format
msgid "Invalid info hash in magnet URL {0}"
msgstr ""
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1500
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "{0} skok"
msgstr[1] "{0} skoki"
msgstr[2] "{0} skoków"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1501
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "{0} tunel"
msgstr[1] "{0} tunele"
msgstr[2] "{0} tuneli"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1663
msgid "Completion"
msgstr ""
#. else unknown
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1667
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716
msgid "Size"
msgstr "Rozmiar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1672
msgid "Files"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1674
msgid "Pieces"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675
msgid "Piece size"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697
msgid "Magnet link"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1753
msgid "Directory"
msgstr "Katalog"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1723
msgid "Priority"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1728
msgid "Up to higher level directory"
msgstr "Do katalogu nadrzędnego"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758
msgid "Torrent not found?"
msgstr "Torrent not found?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1767
msgid "File not found in torrent?"
msgstr "File not found in torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780
msgid "complete"
msgstr "zakończono"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1781
msgid "bytes remaining"
msgstr "bajtów pozostało"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806
msgid "Open"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1832
msgid "High"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1837
msgid "Normal"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842
msgid "Skip"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851
msgid "Save priorities"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1967
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent pobrano z {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent już uruchomiony: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1990
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent już w kolejce: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1996
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Torrent pobrany z {0} jest niepoprawny"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2003
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Torrent nie był pobrany z: {0}"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,981 @@
# 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
#
# <ducki2p@gmail.com>, 2011
# <i2p@robertfoss.se>, 2011
# hottuna <i2p@robertfoss.se>, 2011
# 123hund123 <M8R-ra4r1r@mailinator.com>, 2011
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-10-13 00:30+0000\n"
"PO-Revision-Date: 2011-06-05 14:52+0000\n"
"Last-Translator: digitalmannen <digitalmannen@gmail.com>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.net/projects/p/I2P/"
"team/sv_SE/)\n"
"Language: sv_SE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:355
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr "Gräns för totalt antal uppladdare är bytt till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:357
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr "Gräns för totalt minsta antal uppladdare är bytt till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:369
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Uppladdnings bandbredd bytt till {0}KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:371
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "Minsta uppladdnings bandbredd bytt till {0}KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:383
#, java-format
msgid "Startup delay changed to {0}"
msgstr "Fördröjning vid uppstart bytt till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:394
#, fuzzy, java-format
msgid "Refresh time changed to {0}"
msgstr "Gräns för totalt antal uppladdare är bytt till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:396
#, fuzzy
msgid "Refresh disabled"
msgstr "Ladda om sida"
#: ../java/src/org/klomp/snark/SnarkManager.java:451
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr ""
"I2CP och tunnel förändringar kommer träda i kraft efter alla torrentar "
"stoppats."
#: ../java/src/org/klomp/snark/SnarkManager.java:455
#, fuzzy, java-format
msgid "I2CP options changed to {0}"
msgstr "I2CP-inställningar ändrade till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:460
msgid "Disconnecting old I2CP destination"
msgstr "Kopplat från gammal I2CP destination"
#: ../java/src/org/klomp/snark/SnarkManager.java:462
#, java-format
msgid "I2CP settings changed to {0}"
msgstr "I2CP-inställningar ändrade till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:467
msgid ""
"Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr ""
"Misslyckades med anslutningsförsök med nya inställningar, återställer de "
"gamla I2CP inställningarna"
#: ../java/src/org/klomp/snark/SnarkManager.java:471
msgid "Unable to reconnect with the old settings!"
msgstr "Misslyckades med anslutningsförsök med gamla inställningar!"
#: ../java/src/org/klomp/snark/SnarkManager.java:473
msgid "Reconnected on the new I2CP destination"
msgstr "Återanslöt mot den nya I2CP destinationen"
#: ../java/src/org/klomp/snark/SnarkManager.java:480
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr "I2CP-lyssnar omstartad på grund av \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:492
msgid "New files will be publicly readable"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:494
msgid "New files will not be publicly readable"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:501
msgid "Enabled autostart"
msgstr "Aktiverade automatisk start"
#: ../java/src/org/klomp/snark/SnarkManager.java:503
msgid "Disabled autostart"
msgstr "Avaktiverade automatisk start"
#: ../java/src/org/klomp/snark/SnarkManager.java:509
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr ""
"Aktiverade öppna trackers - torrent måste startas om för att inställningen "
"ska träda i kraft"
#: ../java/src/org/klomp/snark/SnarkManager.java:511
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr ""
"Avaktiverade öppna trackers - torrent måste startas om för att inställningen "
"ska träda i kraft"
#: ../java/src/org/klomp/snark/SnarkManager.java:519
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr ""
"Öppen tracker-lista förändrad - torrent måste startas om för att "
"inställningen ska träda i kraft"
#: ../java/src/org/klomp/snark/SnarkManager.java:526
#, java-format
msgid "{0} theme loaded, return to main i2psnark page to view."
msgstr "{0} tema laddat, återgå till huvudvyn för i2psnark."
#: ../java/src/org/klomp/snark/SnarkManager.java:533
msgid "Configuration unchanged."
msgstr "Inställningar oförändrade"
#: ../java/src/org/klomp/snark/SnarkManager.java:543
#, java-format
msgid "Unable to save the config to {0}"
msgstr "Misslyckades med att spara inställningar till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:608
msgid "Connecting to I2P"
msgstr "Ansluter till I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:611
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr "Problem vid anslutning till I2P - kontrollera dina I2CP-inställningar!"
#: ../java/src/org/klomp/snark/SnarkManager.java:620
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr "Problem: Kunda in lägga till torrent {0}"
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:642
#, java-format
msgid "Cannot open \"{0}\""
msgstr "Kan inte öppna \"{0}\""
#. TODO - if the existing one is a magnet, delete it and add the metainfo instead?
#: ../java/src/org/klomp/snark/SnarkManager.java:661
#: ../java/src/org/klomp/snark/SnarkManager.java:737
#: ../java/src/org/klomp/snark/SnarkManager.java:792
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2015
#, java-format
msgid "Torrent with this info hash is already running: {0}"
msgstr "Torrent med denna infohash körs redan: {0}"
#. addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:668
#, java-format
msgid ""
"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers "
"only."
msgstr ""
"Varning - Inga I2P trackers i \"{0}\", kommer enbart anmäla til öppna "
"trackers i I2P."
#. addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:673
#, java-format
msgid ""
"Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is "
"enabled before starting this torrent."
msgstr ""
"Varning - Inga I2P trackers i \"{0}\". Kontrollera att öppna trackers är "
"påslagna innan denhär torrenten startas."
#: ../java/src/org/klomp/snark/SnarkManager.java:694
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr "Torrent i \"{0}\" är ogiltig"
#: ../java/src/org/klomp/snark/SnarkManager.java:699
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2037
#, java-format
msgid "ERROR - Out of memory, cannot create torrent from {0}"
msgstr "Problem: Minnet har tagit slut, kan inte skapa torrent från {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:711
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr "Torrent tillagd och startad: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:713
#, java-format
msgid "Torrent added: \"{0}\""
msgstr "Torrent tillagd: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:748
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493
#, java-format
msgid "Fetching {0}"
msgstr "Hämtar {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:751
#, java-format
msgid ""
"We have no saved peers and no other torrents are running. Fetch of {0} will "
"not succeed until you start another torrent."
msgstr ""
"Vi har inga sparade nerladdare och inga andra torrents kör. Hämtning av {0} "
"kommer inte lyckas för en annan torrent startas."
#: ../java/src/org/klomp/snark/SnarkManager.java:755
#, java-format
msgid "Adding {0}"
msgstr "Lägger till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:802
#: ../java/src/org/klomp/snark/SnarkManager.java:825
#: ../java/src/org/klomp/snark/SnarkManager.java:1260
#, java-format
msgid "Failed to copy torrent file to {0}"
msgstr "Misslyckades att kopiera torrentfil till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1052
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr "För många filer i \"{0}\" ({1}), tar bort den!"
#: ../java/src/org/klomp/snark/SnarkManager.java:1054
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr "Torrenten \"{0}\" får inte sluta med \".torrent\", tar bort den."
#: ../java/src/org/klomp/snark/SnarkManager.java:1056
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr "Inga delar i \"{0}\", tar bort den."
#: ../java/src/org/klomp/snark/SnarkManager.java:1058
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr "För många delar i \"{0}\", gränden är {1}, raderar den!"
#: ../java/src/org/klomp/snark/SnarkManager.java:1060
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr "För stora delar i \"{0}\" ({1}B), raderar den."
#: ../java/src/org/klomp/snark/SnarkManager.java:1061
#, java-format
msgid "Limit is {0}B"
msgstr "Gränsen är {0}B"
#: ../java/src/org/klomp/snark/SnarkManager.java:1063
#, java-format
msgid "Torrent \"{0}\" has no data, deleting it!"
msgstr "Torrenten \"{0}\" har ingen data, tar bort den!"
#: ../java/src/org/klomp/snark/SnarkManager.java:1071
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr "Torrentar större än {0}B stöds ännu ej, tar bort \"{1}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:1087
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr "Problem: Kunde ej ta bort torrent {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1108
#: ../java/src/org/klomp/snark/SnarkManager.java:1126
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr "Torrent stannad: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:1147
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr "Torrent borttagen: \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:1155
#, java-format
msgid "Adding torrents in {0}"
msgstr "Torrents tillagda i {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1208
#, java-format
msgid "Download finished: {0}"
msgstr "Nerladdning klar: {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1256
#, java-format
msgid "Metainfo received for {0}"
msgstr "Metainfo mottagen till {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1257
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:528
#, java-format
msgid "Starting up torrent {0}"
msgstr "Startar torrent {0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:1313
msgid "Unable to connect to I2P!"
msgstr "Misslyckades med att ansluta till I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:1319
#, java-format
msgid "Unable to add {0}"
msgstr "Misslyckades med att lägga till {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:204
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr "I2PSnark - Anonym bittorrentklient"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:220
msgid "Torrents"
msgstr "Torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:223
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:230
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1033
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:227
msgid "Refresh page"
msgstr "Ladda om sida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:232
msgid "Forum"
msgstr "Forum"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:286
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758
msgid "Status"
msgstr "Status"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:292
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294
msgid "Hide Peers"
msgstr "Göm nerladdare"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:299
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:301
msgid "Show Peers"
msgstr "Visa nerladdare"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1682
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1698
msgid "Torrent"
msgstr "Torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:312
msgid "Estimated time remaining"
msgstr "Uppskattad återstående tid"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315
msgid "ETA"
msgstr "UÅT"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319
msgid "Downloaded"
msgstr "Nerladdat"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:322
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:336
msgid "RX"
msgstr "RX"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:326
msgid "Uploaded"
msgstr "Uppladdat"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:329
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
msgid "TX"
msgstr "TX"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:334
msgid "Down Rate"
msgstr "Nerhastighet"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:339
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:348
msgid "Rate"
msgstr "Hastighet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:344
msgid "Up Rate"
msgstr "Upphastighet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:368
msgid "Stop all torrents and the I2P tunnel"
msgstr "Stoppa alla torrents och I2P-tunneln"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:370
msgid "Stop All"
msgstr "Stoppa alla"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:379
msgid "Start all torrents and the I2P tunnel"
msgstr "Starta alla torrents och I2P-tunneln"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:381
msgid "Start All"
msgstr "Starta alla"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400
msgid "No torrents loaded."
msgstr "Inga torrents laddade."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405
msgid "Totals"
msgstr "Totalt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "{0} torrent"
msgstr[1] "{0} torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:410
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "{0} ansluten nerladdare"
msgstr[1] "{0} anslutna nerladdare"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:499
#, java-format
msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\""
msgstr "Ogiltig URL: Måste starta med \"http://\", \"{0}\" eller \"{1}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:547
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:574
#, java-format
msgid "Magnet deleted: {0}"
msgstr "Magnet borttagen: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:580
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "Torrentfil borttagen: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:596
#, java-format
msgid "Data file deleted: {0}"
msgstr "Datafil borttagen: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:588
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "Datafil kunde inte tas bort: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:607
#, java-format
msgid "Data dir deleted: {0}"
msgstr "Datamapp borttagen: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:644
msgid "Error creating torrent - you must select a tracker"
msgstr "Misslyckades med att skapa torrent - en tracker måste väljas"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:659
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "Torrent skapad för \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:661
#, java-format
msgid ""
"Many I2P trackers require you to register new torrents before seeding - "
"please do so before starting \"{0}\""
msgstr ""
"Många I2P trackers kräver att användare registrerar sig för uppladdning av "
"torrent - gör det innan \"{0}\" startas"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:663
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "Misslyckades med att skapa torrent för \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "Kan ej skapa torrent för data som ej finns: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:669
msgid "Error creating torrent - you must enter a file or directory"
msgstr "Misslyckades med att skapa torrent - en fil eller mapp måste anges"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:672
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Stoppar alla torrents och stänger I2P-tunneln."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683
msgid "I2P tunnel closed."
msgstr "I2P-tunneln är stängd."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:686
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Öppnar I2P-tunneln och startar torrents."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:813
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:819
msgid "Tracker Error"
msgstr "Tracker-fel"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:811
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:815
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:827
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:831
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:843
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:852
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "{0} nerladdare"
msgstr[1] "{0} nerladdare"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:824
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829
msgid "Seeding"
msgstr "Uppladdning"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:833
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1704
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809
msgid "Complete"
msgstr "Färdig"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:841
msgid "OK"
msgstr "Ok"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:845
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:850
msgid "Stalled"
msgstr "Avstannad"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:857
msgid "No Peers"
msgstr "Inga källor"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:859
msgid "Stopped"
msgstr "Stoppad"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:891
msgid "Torrent details"
msgstr "Torrentdetaljer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:903
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1167
msgid "Info"
msgstr "Info"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:918
msgid "View files"
msgstr "Se filer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:920
msgid "Open file"
msgstr "Öppna fil"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962
msgid "Stop the torrent"
msgstr "Stoppa torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:964
msgid "Stop"
msgstr "Stoppa"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974
msgid "Start the torrent"
msgstr "Starta torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:976
msgid "Start"
msgstr "Starta"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "Ta bort torrent från den aktiva listan, tar bort .torrent fil"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:992
#, java-format
msgid ""
"Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded "
"data will not be deleted) ?"
msgstr ""
"Är du säker på att du vill ta bort filen \"{0}.torrent\" (nerladdad data "
"kommer ej tas bort) ?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:995
msgid "Remove"
msgstr "Ta bort"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "Ta bort .torrent filen och tillhörande datafil(er)"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1011
#, java-format
msgid ""
"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded "
"data?"
msgstr ""
"Är du säker på att du vill ta bort torrenten \"{0}\" och all nerladdad data?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1014
msgid "Delete"
msgstr "Ta bort"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1049
msgid "Unknown"
msgstr "Okänd"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061
msgid "Seed"
msgstr "Källa"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1084
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "Ointressant (nerladdaren har inga delar vi behöver)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "Spärra (nerladdaren låter oss inte be dom delar)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1106
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "Ointresserad (vi har inga delar nerladdaren behöver)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1108
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "Spärrar (vi låter inte nerladdaren be dom delar)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1166
#, java-format
msgid "Details at {0} tracker"
msgstr "Detaljer för {0} tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1195
msgid "Add Torrent"
msgstr "Lägg till torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1197
msgid "From URL"
msgstr "Från URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1200
msgid ""
"Enter the torrent file download URL (I2P only), magnet link, or maggot link"
msgstr "Ange URL (inom I2P) till torrent, magnet länl eller maggot länk"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1205
msgid "Add torrent"
msgstr "Lägg till torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1208
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr "Du kan även kopiera .torrent filer till: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210
msgid "Removing a .torrent will cause it to stop."
msgstr "Borttagning av .torrent fil kommer stanna den."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233
msgid "Create Torrent"
msgstr "Skapa torrent"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1236
msgid "Data to seed"
msgstr "Data att ladda upp"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240
msgid "File or directory to seed (must be within the specified path)"
msgstr "Fil eller mapp att ladda upp (måste finnas på angiven plats)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1242
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1723
msgid "Tracker"
msgstr "Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244
msgid "Select a tracker"
msgstr "Välj en tracker"
#. out.write(_("Open trackers and DHT only"));
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1249
msgid "Open trackers only"
msgstr "Enbart öppna trackers"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1264
msgid "or"
msgstr "eller"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267
msgid "Specify custom tracker announce URL"
msgstr "Ange anpassad tracker URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270
msgid "Create torrent"
msgstr "Skapa torrent"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459
msgid "Configuration"
msgstr "Inställningar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295
msgid "Data directory"
msgstr "Datamapp"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297
msgid "Edit i2psnark.config and restart to change"
msgstr "Förändra i2psnark.conig och starta om för att ändra"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301
msgid "Files readable by all"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305
msgid "If checked, other users may access the downloaded files"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1309
msgid "Auto start"
msgstr "Automatisk start"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1313
msgid "If checked, automatically start torrents that are added"
msgstr "Om ikryssad, startas automatiskt tillagda torrents"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1317
msgid "Theme"
msgstr "Tema"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1330
#, fuzzy
msgid "Refresh time"
msgstr "Ladda om sida"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1343
msgid "Never"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1349
msgid "Startup delay"
msgstr "Fördröjning av uppstart"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1351
msgid "minutes"
msgstr "minuter"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1375
msgid "Total uploader limit"
msgstr "Gräns för totalt antal uppladdare"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1378
msgid "peers"
msgstr "nerladdare"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1382
msgid "Up bandwidth limit"
msgstr "Gräns för bandbredd uppåt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1385
msgid "Half available bandwidth recommended."
msgstr "Hälften av tillgänglig bandbredd rekommenderas."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1387
msgid "View or change router bandwidth"
msgstr "Se eller ändra routerns bandbredd"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1391
msgid "Use open trackers also"
msgstr "Använd öppna trackers med"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1395
msgid ""
"If checked, announce torrents to open trackers as well as the tracker listed "
"in the torrent file"
msgstr ""
"Om ikryssad, anmäl torrents till öppna trackers och tracker angiven i "
"torrentfilen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1399
msgid "Open tracker announce URLs"
msgstr "Öppna tracker-anmälnings URL:er"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411
msgid "Inbound Settings"
msgstr "Inkommande inställningar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1417
msgid "Outbound Settings"
msgstr "Utgående inställningar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425
msgid "I2CP host"
msgstr "I2CP-värd"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430
msgid "I2CP port"
msgstr "I2CP-port"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1445
msgid "I2CP options"
msgstr "I2CP-inställningar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450
msgid "Save configuration"
msgstr "Spara inställningar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1475
#, java-format
msgid "Invalid magnet URL {0}"
msgstr "Ogiltig magnet URL {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1509
#, java-format
msgid "Invalid info hash in magnet URL {0}"
msgstr "Ogiltig infohash i magnet URL {0}"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "{0} hopp"
msgstr[1] "{0} hopp"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1540
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "{0} tunnel"
msgstr[1] "{0} tunnlar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1702
msgid "Completion"
msgstr "Färdiställning"
#. else unknown
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1706
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1755
msgid "Size"
msgstr "Storlek"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1711
msgid "Files"
msgstr "Filer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713
msgid "Pieces"
msgstr "Delar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714
msgid "Piece size"
msgstr "Delstorlek"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736
msgid "Magnet link"
msgstr "Magnet länk"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1753
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792
msgid "Directory"
msgstr "Mapp"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1762
msgid "Priority"
msgstr "Prioritet"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1767
msgid "Up to higher level directory"
msgstr "Up till högre mappnivå"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797
msgid "Torrent not found?"
msgstr "Torrent hittades ej?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806
msgid "File not found in torrent?"
msgstr "Fil hittades ej i torrent?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1819
msgid "complete"
msgstr "färdig"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1820
msgid "bytes remaining"
msgstr "bytes kvar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845
msgid "Open"
msgstr "Öppna"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871
msgid "High"
msgstr "Hög"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1876
msgid "Normal"
msgstr "Normal"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1881
msgid "Skip"
msgstr "Hoppa över"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1890
msgid "Save priorities"
msgstr "Spara prioriteter"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2006
#, java-format
msgid "Torrent fetched from {0}"
msgstr "Torrent hämtad från {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2027
#, java-format
msgid "Torrent already running: {0}"
msgstr "Torrent kör redan: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2029
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "Torrent finns redan i kö: {0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "Torrent vid {0} var inte giltig"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2042
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "Torrent kunde inte hämtas från {0}"

View File

@ -0,0 +1,916 @@
# 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
#
# dich_tran <tran.nathan@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-06-11 08:22+0000\n"
"PO-Revision-Date: 2011-05-17 18:05+0000\n"
"Last-Translator: ducki2p <ducki2p@gmail.com>\n"
"Language-Team: Vietnamese (http://www.transifex.net/projects/p/I2P/team/vi/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: vi\n"
"Plural-Forms: nplurals=1; plural=0\n"
#: ../java/src/org/klomp/snark/SnarkManager.java:307
#, java-format
msgid "Total uploaders limit changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:309
#, java-format
msgid "Minimum total uploaders limit is {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:321
#, java-format
msgid "Up BW limit changed to {0}KBps"
msgstr "Giới hạn băng thông lên đổi thành {0}KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:323
#, java-format
msgid "Minimum up bandwidth limit is {0}KBps"
msgstr "Tối thiểu băng thông lên là {0}KBps"
#: ../java/src/org/klomp/snark/SnarkManager.java:335
#, java-format
msgid "Startup delay changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:386
msgid "I2CP and tunnel changes will take effect after stopping all torrents"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:393
msgid "Disconnecting old I2CP destination"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:397
#, java-format
msgid "I2CP settings changed to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:402
msgid ""
"Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:406
msgid "Unable to reconnect with the old settings!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:408
msgid "Reconnected on the new I2CP destination"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:418
#, java-format
msgid "I2CP listener restarted for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:429
msgid "Enabled autostart"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:431
msgid "Disabled autostart"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:437
msgid "Enabled open trackers - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:439
msgid "Disabled open trackers - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:447
msgid "Open Tracker list changed - torrent restart required to take effect."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:454
#, java-format
msgid "{0} theme loaded, return to main i2psnark page to view."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:461
msgid "Configuration unchanged."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:471
#, java-format
msgid "Unable to save the config to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:536
msgid "Connecting to I2P"
msgstr "Nối kết vào I2P"
#: ../java/src/org/klomp/snark/SnarkManager.java:539
msgid "Error connecting to I2P - check your I2CP settings!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:548
#, java-format
msgid "Error: Could not add the torrent {0}"
msgstr ""
#. catch this here so we don't try do delete it below
#: ../java/src/org/klomp/snark/SnarkManager.java:570
#, java-format
msgid "Cannot open \"{0}\""
msgstr ""
#. TODO - if the existing one is a magnet, delete it and add the metainfo
#. instead?
#: ../java/src/org/klomp/snark/SnarkManager.java:589
#: ../java/src/org/klomp/snark/SnarkManager.java:665
#: ../java/src/org/klomp/snark/SnarkManager.java:720
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1976
#, java-format
msgid "Torrent with this info hash is already running: {0}"
msgstr ""
#. addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P
#. open trackers and DHT only.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:596
#, java-format
msgid ""
"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers "
"only."
msgstr ""
#. addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open
#. trackers are disabled, you should enable open trackers or DHT before
#. starting the torrent.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:601
#, java-format
msgid ""
"Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is "
"enabled before starting this torrent."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:622
#, java-format
msgid "Torrent in \"{0}\" is invalid"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:627
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1998
#, java-format
msgid "ERROR - Out of memory, cannot create torrent from {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:639
#, java-format
msgid "Torrent added and started: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:641
#, java-format
msgid "Torrent added: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:676
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:491
#, java-format
msgid "Fetching {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:679
#, java-format
msgid ""
"We have no saved peers and no other torrents are running. Fetch of {0} will "
"not succeed until you start another torrent."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:683
#, java-format
msgid "Adding {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:730
#: ../java/src/org/klomp/snark/SnarkManager.java:753
#: ../java/src/org/klomp/snark/SnarkManager.java:1180
#, java-format
msgid "Failed to copy torrent file to {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:976
#, java-format
msgid "Too many files in \"{0}\" ({1}), deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:978
#, java-format
msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:980
#, java-format
msgid "No pieces in \"{0}\", deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:982
#, java-format
msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:984
#, java-format
msgid "Pieces are too large in \"{0}\" ({1}B), deleting it."
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:985
#, java-format
msgid "Limit is {0}B"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:987
#, java-format
msgid "Torrent \"{0}\" has no data, deleting it!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:995
#, java-format
msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1011
#, java-format
msgid "Error: Could not remove the torrent {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1032
#: ../java/src/org/klomp/snark/SnarkManager.java:1050
#, java-format
msgid "Torrent stopped: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1071
#, java-format
msgid "Torrent removed: \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1079
#, java-format
msgid "Adding torrents in {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1128
#, java-format
msgid "Download finished: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1176
#, java-format
msgid "Metainfo received for {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1177
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:526
#, java-format
msgid "Starting up torrent {0}"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1231
msgid "Unable to connect to I2P!"
msgstr ""
#: ../java/src/org/klomp/snark/SnarkManager.java:1237
#, java-format
msgid "Unable to add {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:205
msgid "I2PSnark - Anonymous BitTorrent Client"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:218
msgid "Torrents"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:221
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:228
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1028
msgid "I2PSnark"
msgstr "I2PSnark"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:225
msgid "Refresh page"
msgstr "Nạp lại trang"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:230
msgid "Forum"
msgstr "Diễn đàn"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1719
msgid "Status"
msgstr "Tình trạng"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:290
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:292
msgid "Hide Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:297
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:299
msgid "Show Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:306
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1659
msgid "Torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:310
msgid "Estimated time remaining"
msgstr ""
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313
msgid "ETA"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:317
msgid "Downloaded"
msgstr "Đã tải xuống"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:320
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:334
msgid "RX"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324
msgid "Uploaded"
msgstr "Đã tải lên"
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:327
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:344
msgid "TX"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:332
msgid "Down Rate"
msgstr ""
#. Translators: Please keep short or translate as " "
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:337
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346
msgid "Rate"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:342
msgid "Up Rate"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:366
msgid "Stop all torrents and the I2P tunnel"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:368
msgid "Stop All"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
msgid "Start all torrents and the I2P tunnel"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:379
msgid "Start All"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398
msgid "No torrents loaded."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:403
msgid "Totals"
msgstr "Tổng cộng"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:408
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:497
#, java-format
msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:545
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:572
#, java-format
msgid "Magnet deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:553
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:578
#, java-format
msgid "Torrent file deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:584
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:594
#, java-format
msgid "Data file deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:596
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:605
#, java-format
msgid "Data dir deleted: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:638
msgid "Error creating torrent - you must select a tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:653
#, java-format
msgid "Torrent created for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:655
#, 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:657
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:663
msgid "Error creating torrent - you must enter a file or directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:677
msgid "I2P tunnel closed."
msgstr "Đường hầm I2P đóng lại."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
msgid "Opening the I2P tunnel and starting all torrents."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:803
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814
msgid "Tracker Error"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:806
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:822
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:834
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:838
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:843
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:847
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:819
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:824
msgid "Seeding"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1770
msgid "Complete"
msgstr "Hoàn tất"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:831
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
msgid "OK"
msgstr "OK"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:840
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:845
msgid "Stalled"
msgstr "Khựng"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:849
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:852
msgid "No Peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854
msgid "Stopped"
msgstr "Ngưng"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:886
msgid "Torrent details"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:898
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1160
msgid "Info"
msgstr "Thông tin"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:913
msgid "View files"
msgstr "Xem tập tin"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:915
msgid "Open file"
msgstr "Mở tập tin"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:957
msgid "Stop the torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:959
msgid "Stop"
msgstr "Ngưng"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
msgid "Start the torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:971
msgid "Start"
msgstr "Bắt đầu"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr ""
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
#, java-format
msgid ""
"Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded "
"data will not be deleted) ?"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:990
msgid "Remove"
msgstr "Bỏ"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
msgid "Delete the .torrent file and the associated data file(s)"
msgstr ""
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
#, java-format
msgid ""
"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded "
"data?"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1009
msgid "Delete"
msgstr "Xóa"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042
msgid "Unknown"
msgstr "Không rõ"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054
msgid "Seed"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077
msgid "Uninteresting (The peer has no pieces we need)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1079
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1099
msgid "Uninterested (We have no pieces the peer needs)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1101
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1159
#, java-format
msgid "Details at {0} tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1188
msgid "Add Torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190
msgid "From URL"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1193
msgid ""
"Enter the torrent file download URL (I2P only), magnet link, or maggot link"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1198
msgid "Add torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1201
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1203
msgid "Removing a .torrent will cause it to stop."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226
msgid "Create Torrent"
msgstr ""
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\"
#. value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229
msgid "Data to seed"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233
msgid "File or directory to seed (must be within the specified path)"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684
msgid "Tracker"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
msgid "Select a tracker"
msgstr ""
#. out.write(_("Open trackers and DHT only"));
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1242
msgid "Open trackers only"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1257
msgid "or"
msgstr "hoặc"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1260
msgid "Specify custom tracker announce URL"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263
msgid "Create torrent"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1420
msgid "Configuration"
msgstr "Cấu hình"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1285
msgid "Data directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287
msgid "Edit i2psnark.config and restart to change"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
msgid "Auto start"
msgstr "Tự động bắt đầu"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295
msgid "If checked, automatically start torrents that are added"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1299
msgid "Theme"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1312
msgid "Startup delay"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1314
msgid "minutes"
msgstr "phút"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338
msgid "Total uploader limit"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1341
msgid "peers"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1345
msgid "Up bandwidth limit"
msgstr "Giới hạn băng thông lên"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1348
msgid "Half available bandwidth recommended."
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1350
msgid "View or change router bandwidth"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1354
msgid "Use open trackers also"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358
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:1362
msgid "Open tracker announce URLs"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1374
msgid "Inbound Settings"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1380
msgid "Outbound Settings"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1388
msgid "I2CP host"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1393
msgid "I2CP port"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1406
msgid "I2CP options"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411
msgid "Save configuration"
msgstr "Lưu cấu hình"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1436
#, java-format
msgid "Invalid magnet URL {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1470
#, java-format
msgid "Invalid info hash in magnet URL {0}"
msgstr ""
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1500
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1501
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1663
msgid "Completion"
msgstr ""
#. else unknown
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1667
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716
msgid "Size"
msgstr "Kích thước"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1672
msgid "Files"
msgstr "Tập tin"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1674
msgid "Pieces"
msgstr "Mảnh"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675
msgid "Piece size"
msgstr "Kích thước mảnh"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697
msgid "Magnet link"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1753
msgid "Directory"
msgstr "Danh mục"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1723
msgid "Priority"
msgstr "Ưu tiên"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1728
msgid "Up to higher level directory"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758
msgid "Torrent not found?"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1767
msgid "File not found in torrent?"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780
msgid "complete"
msgstr "hoàn tất"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1781
msgid "bytes remaining"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806
msgid "Open"
msgstr "Mở"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1832
msgid "High"
msgstr "Cao"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1837
msgid "Normal"
msgstr "Thường"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842
msgid "Skip"
msgstr "Lờ"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851
msgid "Save priorities"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1967
#, java-format
msgid "Torrent fetched from {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988
#, java-format
msgid "Torrent already running: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1990
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1996
#, java-format
msgid "Torrent at {0} was not valid"
msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2003
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr ""

View File

@ -8,10 +8,11 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-20 07:23+0000\n"
"POT-Creation-Date: 2011-03-03 18:28+0000\n"
"PO-Revision-Date: 2011-02-20 15:26+0800\n"
"Last-Translator: \n"
"Language-Team: foo <foo@bar>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -57,7 +58,8 @@ msgid "I2CP settings changed to {0}"
msgstr "I2CP设置改为{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:402
msgid "Unable to connect with the new settings, reverting to the old I2CP settings"
msgid ""
"Unable to connect with the new settings, reverting to the old I2CP settings"
msgstr "无法通过新设置连接恢复I2CP的旧设置"
#: ../java/src/org/klomp/snark/SnarkManager.java:406
@ -130,7 +132,7 @@ msgstr "无法打开 \"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:586
#: ../java/src/org/klomp/snark/SnarkManager.java:661
#: ../java/src/org/klomp/snark/SnarkManager.java:716
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1976
#, java-format
msgid "Torrent with this info hash is already running: {0}"
msgstr "具有相同Hash链接的种子已在下载中:{0}"
@ -138,14 +140,21 @@ msgstr "具有相同Hash链接的种子已在下载中:{0}"
#. addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:593
#, java-format
msgid "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only."
msgstr "提示 - “{0}”文件中不包含 I2P Tracker服务器,文件将仅发布至 I2P 的 Open Tracker "
msgid ""
"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers "
"only."
msgstr ""
"提示 - “{0}”文件中不包含 I2P Tracker服务器文件将仅发布至 I2P 的 Open "
"Tracker 。"
#. addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName()));
#: ../java/src/org/klomp/snark/SnarkManager.java:598
#, java-format
msgid "Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is enabled before starting this torrent."
msgstr "警告 -“{0}”中不包含 I2P Tracker 服务器,下载此种子请先启用 Open Tracker"
msgid ""
"Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is "
"enabled before starting this torrent."
msgstr ""
"警告 -“{0}”中不包含 I2P Tracker 服务器,下载此种子请先启用 Open Tracker。"
#: ../java/src/org/klomp/snark/SnarkManager.java:619
#, java-format
@ -153,7 +162,7 @@ msgid "Torrent in \"{0}\" is invalid"
msgstr "无效种子 \"{0}\" "
#: ../java/src/org/klomp/snark/SnarkManager.java:624
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1994
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1999
#, java-format
msgid "ERROR - Out of memory, cannot create torrent from {0}"
msgstr "错误: 内存不足,无法为 {0} 创建种子。"
@ -169,15 +178,19 @@ msgid "Torrent added: \"{0}\""
msgstr "已添加种子:\"{0}\""
#: ../java/src/org/klomp/snark/SnarkManager.java:672
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:489
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:490
#, java-format
msgid "Fetching {0}"
msgstr "正在获取{0}"
#: ../java/src/org/klomp/snark/SnarkManager.java:675
#, java-format
msgid "We have no saved peers and no other torrents are running. Fetch of {0} will not succeed until you start another torrent."
msgstr "程序还不知道其他客户端的存在,目前也没有其他种子正在运行。在您启动其他种子前文件 {0} 无法成功下载。"
msgid ""
"We have no saved peers and no other torrents are running. Fetch of {0} will "
"not succeed until you start another torrent."
msgstr ""
"程序还不知道其他客户端的存在,目前也没有其他种子正在运行。在您启动其他种子前"
"文件 {0} 无法成功下载。"
#: ../java/src/org/klomp/snark/SnarkManager.java:679
#, java-format
@ -258,7 +271,7 @@ msgid "Metainfo received for {0}"
msgstr "已获得 {0} 的 Metainfo"
#: ../java/src/org/klomp/snark/SnarkManager.java:1171
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:525
#, java-format
msgid "Starting up torrent {0}"
msgstr "正在启动种子{0}"
@ -282,7 +295,7 @@ msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:221
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:228
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1024
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1028
msgid "I2PSnark"
msgstr "I2PSnark"
@ -295,7 +308,7 @@ msgid "Forum"
msgstr "论坛"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1715
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1719
msgid "Status"
msgstr "状态"
@ -310,8 +323,8 @@ msgid "Show Peers"
msgstr "显示用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:306
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1639
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1655
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1659
msgid "Torrent"
msgstr "种子"
@ -358,682 +371,725 @@ msgstr "速度"
msgid "Up Rate"
msgstr "上传速度"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:364
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:365
msgid "Stop all torrents and the I2P tunnel"
msgstr "停止全部种子及I2P隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:366
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:367
msgid "Stop All"
msgstr "停止全部"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:375
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:376
msgid "Start all torrents and the I2P tunnel"
msgstr "启动全部种子及I2P隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:377
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:378
msgid "Start All"
msgstr "启动全部"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:397
msgid "No torrents loaded."
msgstr "未载入任何种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:401
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:402
msgid "Totals"
msgstr "总计"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:403
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:404
#, java-format
msgid "1 torrent"
msgid_plural "{0} torrents"
msgstr[0] "{0}个种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:406
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407
#, java-format
msgid "1 connected peer"
msgid_plural "{0} connected peers"
msgstr[0] "{0}个已连接用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496
#, java-format
msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\""
msgstr "无效链接 - 链接必须以“http://”,“{0}”或“{1}”开头"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:543
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:544
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571
#, java-format
msgid "Magnet deleted: {0}"
msgstr "Magnet 已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:551
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:576
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:552
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:577
#, java-format
msgid "Torrent file deleted: {0}"
msgstr "种子文件已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:582
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:592
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:593
#, java-format
msgid "Data file deleted: {0}"
msgstr "数据文件已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:584
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:594
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:595
#, java-format
msgid "Data file could not be deleted: {0}"
msgstr "无法删除数据文件:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:603
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604
#, java-format
msgid "Data dir deleted: {0}"
msgstr "数据文件夹已删除:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:636
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:637
msgid "Error creating torrent - you must select a tracker"
msgstr "创建种子时发生错误 - 您必须选择一个Tracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:652
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:653
#, java-format
msgid "Torrent created for \"{0}\""
msgstr "种子创建成功\"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:654
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:655
#, java-format
msgid "Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\""
msgstr "多数I2PTracker需要用户在做种前注册新种子 - 请在启动 \"{0}\"前到所使用的Tracker进行注册。"
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:656
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657
#, java-format
msgid "Error creating a torrent for \"{0}\""
msgstr "创建种子时发生错误 \"{0}\""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:659
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660
#, java-format
msgid "Cannot create a torrent for the nonexistent data: {0}"
msgstr "无法为不存在的数据文件创建种子:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:662
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:663
msgid "Error creating torrent - you must enter a file or directory"
msgstr "创建种子时发生错误 - 必须指定文件或文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:666
msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "正在停用所有种子并关闭I2P隧道。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:677
msgid "I2P tunnel closed."
msgstr "I2P隧道已关闭"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:679
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:680
msgid "Opening the I2P tunnel and starting all torrents."
msgstr "正在打开I2P隧道并启动所有种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:802
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:807
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:813
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:803
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:808
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814
msgid "Tracker Error"
msgstr "Tracker错误"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:805
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:809
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:833
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:842
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:846
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:806
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:810
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:822
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:834
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:838
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:843
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:847
#, java-format
msgid "1 peer"
msgid_plural "{0} peers"
msgstr[0] "{0}个用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:818
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:819
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:824
msgid "Seeding"
msgstr "正做种"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:827
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1661
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1766
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1665
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1770
msgid "Complete"
msgstr "完成"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:830
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:831
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:836
msgid "OK"
msgstr "确定"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:844
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:840
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:845
msgid "Stalled"
msgstr "等待"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:851
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:849
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:852
msgid "No Peers"
msgstr "没有用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:853
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854
msgid "Stopped"
msgstr "已停用"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:885
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:886
msgid "Torrent details"
msgstr "种子详情"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:897
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1156
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:898
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1160
msgid "Info"
msgstr "信息"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:912
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:913
msgid "View files"
msgstr "浏览文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:914
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:915
msgid "Open file"
msgstr "打开文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:956
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:957
msgid "Stop the torrent"
msgstr "停止种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:959
msgid "Stop"
msgstr "停止"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:967
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
msgid "Start the torrent"
msgstr "启动种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:969
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:971
msgid "Start"
msgstr "启动"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:982
msgid "Remove the torrent from the active list, deleting the .torrent file"
msgstr "取消下载任务并删除对应种子文件。"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:984
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
#, java-format
msgid "Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?"
msgid ""
"Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded "
"data will not be deleted) ?"
msgstr "您确定要删除文件“{0}.torrent”(下载的数据文件不会被删除)?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:987
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:990
msgid "Remove"
msgstr "移除"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:997
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1001
msgid "Delete the .torrent file and the associated data file(s)"
msgstr "删除种子及所下载的文件"
#. Can't figure out how to escape double quotes inside the onclick string.
#. Single quotes in translate strings with parameters must be doubled.
#. Then the remaining single quite must be escaped
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1002
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1006
#, java-format
msgid "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?"
msgid ""
"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded "
"data?"
msgstr "您确定要删除种子“{0}”(下载的数据文件会一并被删除)?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1005
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1009
msgid "Delete"
msgstr "删除"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1038
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042
msgid "Unknown"
msgstr "未知"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1050
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054
msgid "Seed"
msgstr "种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1073
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077
msgid "Uninteresting (The peer has no pieces we need)"
msgstr "无需要部分"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1075
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1079
msgid "Choked (The peer is not allowing us to request pieces)"
msgstr "拒绝请求"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1095
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1099
msgid "Uninterested (We have no pieces the peer needs)"
msgstr "无需要部分"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1097
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1101
msgid "Choking (We are not allowing the peer to request pieces)"
msgstr "拒绝请求"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1155
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1159
#, java-format
msgid "Details at {0} tracker"
msgstr "Tracker {0} 上的详细信息"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1184
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1188
msgid "Add Torrent"
msgstr "添加种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1186
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190
msgid "From URL"
msgstr "从URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1189
msgid "Enter the torrent file download URL (I2P only), magnet link, or maggot link"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1193
msgid ""
"Enter the torrent file download URL (I2P only), magnet link, or maggot link"
msgstr "请输入输入 torrent 文件下载链接(仅限.i2p)、magnet 链接或 maggot 链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1194
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1198
msgid "Add torrent"
msgstr "添加种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1197
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1201
#, java-format
msgid "You can also copy .torrent files to: {0}."
msgstr "您也可以将.torrent文件复制到: {0}."
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1199
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1203
msgid "Removing a .torrent will cause it to stop."
msgstr "删除种子文件将导致该下载任务中止。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1222
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226
msgid "Create Torrent"
msgstr "创建种子"
#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1225
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229
msgid "Data to seed"
msgstr "做种数据"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233
msgid "File or directory to seed (must be within the specified path)"
msgstr "做种文件或文件夹(必须下面为Snark指定的文件夹中)"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684
msgid "Tracker"
msgstr "Tracker服务器"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1237
msgid "Select a tracker"
msgstr "选择一个Tracker"
#. out.write(_("Open trackers and DHT only"));
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1238
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1242
msgid "Open trackers only"
msgstr "仅通过 Open Tracker发布链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1257
msgid "or"
msgstr "或"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1260
msgid "Specify custom tracker announce URL"
msgstr "指定Open Tracker发布链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263
msgid "Create torrent"
msgstr "创建种子"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1420
msgid "Configuration"
msgstr "设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1285
msgid "Data directory"
msgstr "数据文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287
msgid "Edit i2psnark.config and restart to change"
msgstr "编辑 i2psnark.config 并重启Snark后生效"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
msgid "Auto start"
msgstr "自动启动"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1291
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295
msgid "If checked, automatically start torrents that are added"
msgstr "选中后Snark将自动启动已添加的所有种子。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1299
msgid "Theme"
msgstr "主题"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1308
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1312
msgid "Startup delay"
msgstr "启动延迟"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1314
msgid "minutes"
msgstr "分"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1334
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338
msgid "Total uploader limit"
msgstr "限制总上传种子数为"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1337
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1341
msgid "peers"
msgstr "用户"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1341
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1345
msgid "Up bandwidth limit"
msgstr "上传带宽限制"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1344
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1348
msgid "Half available bandwidth recommended."
msgstr "推荐设置为可用带宽的一半。"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1346
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1350
msgid "View or change router bandwidth"
msgstr "浏览或修改路由器带宽"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1350
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1354
msgid "Use open trackers also"
msgstr "同时使用OpenTracker"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1354
msgid "If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358
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:1358
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1362
msgid "Open tracker announce URLs"
msgstr "Open Tracker发布链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1374
msgid "Inbound Settings"
msgstr "入站设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1376
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1380
msgid "Outbound Settings"
msgstr "出站设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1384
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1388
msgid "I2CP host"
msgstr "I2CP主机"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1389
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1393
msgid "I2CP port"
msgstr "I2CP端口"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1406
msgid "I2CP options"
msgstr "I2CP选项"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1407
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411
msgid "Save configuration"
msgstr "保存设置"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1432
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1436
#, java-format
msgid "Invalid magnet URL {0}"
msgstr "磁性链接 {0} 无效"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1466
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1470
#, java-format
msgid "Invalid info hash in magnet URL {0}"
msgstr "magnet磁性链接“{0}”中的hash信息有误。"
#. * dummies for translation
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1496
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1500
#, java-format
msgid "1 hop"
msgid_plural "{0} hops"
msgstr[0] "{0}跳"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1497
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1501
#, java-format
msgid "1 tunnel"
msgid_plural "{0} tunnels"
msgstr[0] "{0}隧道"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1659
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1663
msgid "Completion"
msgstr "完成"
#. else unknown
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1663
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1667
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716
msgid "Size"
msgstr "大小"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1668
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1672
msgid "Files"
msgstr "文件"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1670
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1674
msgid "Pieces"
msgstr "分块数量"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1671
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675
msgid "Piece size"
msgstr "分块大小"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1693
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697
msgid "Magnet link"
msgstr "Magnet磁性链接"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1710
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1753
msgid "Directory"
msgstr "文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1719
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1723
msgid "Priority"
msgstr "优先级"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1728
msgid "Up to higher level directory"
msgstr "上一层文件夹"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758
msgid "Torrent not found?"
msgstr "种子未找到"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1763
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1767
msgid "File not found in torrent?"
msgstr "种子中没有发现文件?"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1776
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780
msgid "complete"
msgstr "完成"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1777
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1781
msgid "bytes remaining"
msgstr "剩余字节数"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1802
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806
msgid "Open"
msgstr "打开"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1828
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1832
msgid "High"
msgstr "高"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1833
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1837
msgid "Normal"
msgstr "普通"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842
msgid "Skip"
msgstr "跳过"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851
msgid "Save priorities"
msgstr "保存优先级"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1962
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1967
#, java-format
msgid "Torrent fetched from {0}"
msgstr "从{0}获取种子成功"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1989
#, java-format
msgid "Torrent already running: {0}"
msgstr "种子已启动:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1991
#, java-format
msgid "Torrent already in the queue: {0}"
msgstr "种子排队中:{0}"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1992
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997
#, java-format
msgid "Torrent at {0} was not valid"
msgstr "{0}的种子中有错误"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1999
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2004
#, java-format
msgid "Torrent was not retrieved from {0}"
msgstr "从{0}获得种子失败"
#~ msgid "Torrent file must originate from an I2P-based tracker"
#~ msgstr "种子文件必须来在I2P内网中的Tracker服务器。"
#~ msgid "size: {0}B"
#~ msgstr "大小:{0}B"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/status.png\" title="
#~ "\"Torrent Status\">Status"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/status.png\" title="
#~ "\"种子状态\">状态"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/showpeers.png\" "
#~ "title=\"Toggle Peer Visibility\" alt=\"Hide Peers\">"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/showpeers.png\" "
#~ "title=\"隐藏节点\" alt=\"隐藏节点\">"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/hidepeers.png\" "
#~ "title=\"Toggle Peer Visibility\" alt=\"Show Peers\">"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/hidepeers.png\" "
#~ "title=\"显示节点\" alt=\"显示节点\">"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/torrent.png\" title="
#~ "\"Loaded Torrents\">Torrent"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/torrent.png\" title="
#~ "\"载入的种子\">种子"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/eta.png\" title="
#~ "\"Estimated Download Time\">ETA"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/eta.png\" title=\"预"
#~ "计剩余时间\">预计剩余时间"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"Data "
#~ "Downloaded\">RX"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"下载"
#~ "数据量\">下载"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/images/outbound.png\" title="
#~ "\"Data Uploaded\">TX"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/images/outbound.png\" title=\"上传"
#~ "数据量\">上传"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/images/inbound.png\" title="
#~ "\"Download Speed\">Rate"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"下载"
#~ "速度\">下载速度"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/images/outbound.png\" title="
#~ "\"Upload Speed\">Rate"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/images/outbound.png\" title=\"上传"
#~ "速度\">上传速度"
#~ msgid ""
#~ "<img src=\"/themes/console/snark/images/stop_all.png\" title=\"Stop All "
#~ "Torrents\" alt=\"Stop All\">"
#~ msgstr ""
#~ "<img src=\"/themes/console/snark/images/stop_all.png\" title=\"全部停止\" "
#~ "alt=\"全部停止\">"
#~ msgid ""
#~ "<img src=\"/themes/console/snark/images/start_all.png\" title=\"Start All "
#~ "Torrents\" alt=\"Start All\">"
#~ msgstr ""
#~ "<img src=\"/themes/console/snark/images/start_all.png\" title=\"全部开始"
#~ "\" alt=\"全部开始\">"
#~ msgid "Torrent file {0} does not exist"
#~ msgstr "种子文件{0}不存在"
#~ msgid "Copying torrent to {0}"
#~ msgstr "正在复制种子到{0}"
#~ msgid "from {0}"
#~ msgstr "来源{0}"
#~ msgid ""
#~ "<img src=\"/themes/console/snark/images/stop.png\" title=\"Stop Torrent\" "
#~ "alt=\"Stop\">"
#~ msgstr ""
#~ "<img src=\"/themes/console/snark/images/stop.png\" title=\"停止下载\" alt="
#~ "\"停止\">"
#~ msgid ""
#~ "<img src=\"/themes/console/snark/images/start.png\" title=\"Start Torrent"
#~ "\" alt=\"Start\">"
#~ msgstr ""
#~ "<img src=\"/themes/console/snark/images/start.png\" title=\"开始下载\" "
#~ "alt=\"开始\">"
#~ msgid ""
#~ "<img src=\"/themes/console/snark/images/remove.png\" title=\"Remove "
#~ "Torrent\" alt=\"Remove\">"
#~ msgstr ""
#~ "<img src=\"/themes/console/snark/images/remove.png\" title=\"删除种子\" "
#~ "alt=\"删除种子\">"
#~ msgid ""
#~ "<img src=\"/themes/console/snark/images/delete.png\" title=\"Delete "
#~ "Torrent + Data\" alt=\"Delete\">"
#~ msgstr ""
#~ "<img src=\"/themes/console/snark/images/delete.png\" title=\"删除种子 + 数"
#~ "据\" alt=\"删除种子 + 数据\">"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/add.png\">Add Torrent"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/add.png\">添加种子"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/create.png\">Create "
#~ "Torrent"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/create.png\">创建种子"
#~ msgid "or&nbsp;"
#~ msgstr "或&nbsp;"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/config.png"
#~ "\">Configuration"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/config.png\">设置"
#~ msgid "Directory to store torrents and data"
#~ msgstr "种子及被做种文件的保存位置。"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/file.png\" title="
#~ "\"File\" alt=\"File\">&nbsp;"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/file.png\" title=\"文"
#~ "件\" alt=\"文件\">&nbsp;"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/size.png\" title="
#~ "\"FileSize\" alt=\"FileSize\">Size"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/size.png\" title=\"文"
#~ "件大小\" alt=\"文件大小\">大小"
#~ msgid ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/status.png\" title="
#~ "\"Download Status\">Status"
#~ msgstr ""
#~ "<img border=\"0\" src=\"/themes/console/snark/images/status.png\" title="
#~ "\"下载状态\">状态"
#~ msgid "Details"
#~ msgstr "详情"
#~ msgid "Cannot change the I2CP settings while torrents are active"
#~ msgstr "正在下载/上传无法更改I2CP设置"
#~ msgid "{0} torrents"
#~ msgstr "{0} 个种子"
#~ msgid "Non-i2p tracker in \"{0}\", deleting it from our list of trackers!"
#~ msgstr ""
#~ "【匿名性警告】\"{0}\" 中含有非I2P Tracker程序将从Tracker列表中将其删除。"
#~ msgid "Custom tracker URL"
#~ msgstr "自定义TrackerURL"
#~ msgid "Configure"
#~ msgstr "设置"

View File

@ -20,7 +20,10 @@
</classpath>
</depend>
</target>
<property name="javac.compilerargs" value="" />
<property name="require.gettext" value="true" />
<target name="compile" depends="depend">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
@ -34,10 +37,7 @@
</javac>
</target>
<!-- TODO: Move the web classes from the jar to the war - they are not part of the API
- This will require sponge to rewrite some seedless stuff that uses it.
-->
<target name="jar" depends="builddep, compile, jarUpToDate" unless="jar.uptodate" >
<target name="listChangedFiles" depends="jarUpToDate" if="shouldListChanges" >
<exec executable="mtn" outputproperty="workspace.changes.j" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
@ -49,6 +49,15 @@
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<!-- TODO: Move the web classes from the jar to the war - they are not part of the API
- This will require sponge to rewrite some seedless stuff that uses it.
-->
<target name="jar" depends="builddep, compile, jarUpToDate, listChangedFiles" unless="jar.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.j.tr" value="" />
<jar destfile="./build/i2ptunnel.jar" basedir="./build/obj" includes="**/*.class">
<manifest>
<attribute name="Main-Class" value="net.i2p.i2ptunnel.I2PTunnel" />
@ -64,15 +73,23 @@
<uptodate property="jar.uptodate" targetfile="build/i2ptunnel.jar" >
<srcfiles dir= "build/obj" includes="**/*.class" />
</uptodate>
<condition property="shouldListChanges" >
<and>
<not>
<isset property="jar.uptodate" />
</not>
<isset property="mtn.available" />
</and>
</condition>
</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="true" >
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<arg value="./bundle-messages.sh" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >
<arg value="./bundle-messages.sh" />
</exec>
<!-- multi-lang is optional -->
@ -83,21 +100,21 @@
<target name="poupdate" depends="compile, precompilejsp">
<!-- Update the messages_*.po files. -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" >
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
<exec executable="sh" osfamily="windows" failifexecutionfails="true" >
<exec executable="sh" osfamily="windows" failifexecutionfails="true" failonerror="true" >
<arg value="./bundle-messages.sh" />
<arg value="-p" />
</exec>
</target>
<target name="war" depends="precompilejsp, bundle, warUpToDate" unless="war.uptodate" >
<target name="listChangedFiles2" depends="warUpToDate" if="shouldListChanges2" >
<exec executable="mtn" outputproperty="workspace.changes.w" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
@ -109,6 +126,11 @@
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<target name="war" depends="precompilejsp, bundle, warUpToDate, listChangedFiles2" unless="war.uptodate" >
<!-- set if unset -->
<property name="workspace.changes.w.tr" value="" />
<war destfile="build/i2ptunnel.war" webxml="../jsp/web-out.xml"
basedir="../jsp/" excludes="web.xml, web-fragment.xml, web-out.xml, **/*.java, *.jsp">
<manifest>
@ -123,6 +145,14 @@
<uptodate property="war.uptodate" targetfile="build/i2ptunnel.war" >
<srcfiles dir= "../jsp" excludes="web.xml, web-fragment.xml, **/*.java, *.jsp" />
</uptodate>
<condition property="shouldListChanges2" >
<and>
<not>
<isset property="war.uptodate" />
</not>
<isset property="mtn.available" />
</and>
</condition>
</target>
<target name="precompilejsp" depends="jar" unless="precompilejsp.uptodate">

View File

@ -12,6 +12,7 @@
CLASS=net.i2p.i2ptunnel.web.messages
TMPFILE=build/javafiles.txt
export TZ=UTC
RC=0
if [ "$1" = "-p" ]
then
@ -69,15 +70,17 @@ do
-o ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - xgettext failed, not updating translations'
echo "ERROR - xgettext failed on ${i}, not updating translations"
rm -f ${i}t
RC=1
break
fi
msgmerge -U --backup=none $i ${i}t
if [ $? -ne 0 ]
then
echo 'Warning - msgmerge failed, not updating translations'
echo "ERROR - msgmerge failed on ${i}, not updating translations"
rm -f ${i}t
RC=1
break
fi
rm -f ${i}t
@ -94,11 +97,13 @@ do
msgfmt --java --statistics -r $CLASS -l $LG -d ../jsp/WEB-INF/classes $i
if [ $? -ne 0 ]
then
echo 'Warning - msgfmt failed, not updating translations'
echo "ERROR - msgfmt failed on ${i}, not updating translations"
# msgfmt leaves the class file there so the build would work the next time
find src/WEB-INF/classes -name messages_${LG}.class -exec rm -f {} \;
RC=1
break
fi
fi
done
rm -f $TMPFILE
# todo: return failure
exit 0
exit $RC

View File

@ -20,9 +20,11 @@ import java.util.concurrent.RejectedExecutionException;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
import net.i2p.util.BigPipedInputStream;
import net.i2p.util.ByteCache;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.ReusableGZIPInputStream;
/**
* This does the transparent gzip decompression on the client side.
@ -44,7 +46,9 @@ class HTTPResponseOutputStream extends FilterOutputStream {
private final byte _buf1[];
protected boolean _gzip;
private long _dataWritten;
private InternalGZIPInputStream _in;
protected long _dataExpected;
protected String _contentType;
private static final int CACHE_SIZE = 8*1024;
private static final ByteCache _cache = ByteCache.getInstance(8, CACHE_SIZE);
// OOM DOS prevention
@ -129,10 +133,11 @@ class HTTPResponseOutputStream extends FilterOutputStream {
}
/**
* Tweak that first HTTP response line (HTTP 200 OK, etc)
* Possibly tweak that first HTTP response line (HTTP/1.0 200 OK, etc).
* Overridden on server side.
*
*/
protected static String filterResponseLine(String line) {
protected String filterResponseLine(String line) {
return line;
}
@ -183,6 +188,15 @@ class HTTPResponseOutputStream extends FilterOutputStream {
} else if ("Proxy-Authenticate".equalsIgnoreCase(key)) {
// filter this hop-by-hop header; outproxy authentication must be configured in I2PTunnelHTTPClient
} else {
if ("Content-Length".equalsIgnoreCase(key)) {
// save for compress decision on server side
try {
_dataExpected = Long.parseLong(val);
} catch (NumberFormatException nfe) {}
} else if ("Content-Type".equalsIgnoreCase(key)) {
// save for compress decision on server side
_contentType = val;
}
out.write((key.trim() + ": " + val.trim() + "\r\n").getBytes());
}
break;
@ -227,13 +241,13 @@ class HTTPResponseOutputStream extends FilterOutputStream {
protected void beginProcessing() throws IOException {
//out.flush();
PipedInputStream pi = new PipedInputStream();
PipedInputStream pi = BigPipedInputStream.getInstance();
PipedOutputStream po = new PipedOutputStream(pi);
// Run in the client thread pool, as there should be an unused thread
// there after the accept().
// Overridden in I2PTunnelHTTPServer, where it does not use the client pool.
try {
I2PTunnelClientBase._executor.execute(new Pusher(pi, out));
I2PTunnelClientBase.getClientExecutor().execute(new Pusher(pi, out));
} catch (RejectedExecutionException ree) {
// shouldn't happen
throw ree;
@ -242,25 +256,29 @@ class HTTPResponseOutputStream extends FilterOutputStream {
}
private class Pusher implements Runnable {
private InputStream _inRaw;
private OutputStream _out;
private final InputStream _inRaw;
private final OutputStream _out;
public Pusher(InputStream in, OutputStream out) {
_inRaw = in;
_out = out;
}
public void run() {
_in = null;
ReusableGZIPInputStream _in = null;
long written = 0;
ByteArray ba = null;
try {
_in = new InternalGZIPInputStream(_inRaw);
_in = ReusableGZIPInputStream.acquire();
// blocking
_in.initialize(_inRaw);
ba = _cache.acquire();
byte buf[] = ba.getData();
int read = -1;
while ( (read = _in.read(buf)) != -1) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Read " + read + " and writing it to the browser/streams");
_out.write(buf, 0, read);
; _out.write(buf, 0, read);
_out.flush();
written += read;
}
@ -272,13 +290,11 @@ class HTTPResponseOutputStream extends FilterOutputStream {
} catch (OutOfMemoryError oom) {
_log.error("OOM in HTTP Decompressor", oom);
} finally {
if (_log.shouldLog(Log.WARN) && (_in != null))
_log.warn("After decompression, written=" + written +
(_in != null ?
if (_log.shouldLog(Log.INFO) && (_in != null))
_log.info("After decompression, written=" + written +
" read=" + _in.getTotalRead()
+ ", expanded=" + _in.getTotalExpanded() + ", remaining=" + _in.getRemaining()
+ ", finished=" + _in.getFinished()
: ""));
+ ", finished=" + _in.getFinished());
if (ba != null)
_cache.release(ba);
if (_out != null) try {
@ -286,68 +302,21 @@ class HTTPResponseOutputStream extends FilterOutputStream {
} catch (IOException ioe) {}
}
double compressed = (_in != null ? _in.getTotalRead() : 0);
double expanded = (_in != null ? _in.getTotalExpanded() : 0);
if (compressed > 0 && expanded > 0) {
// only update the stats if we did something
double ratio = compressed/expanded;
_context.statManager().addRateData("i2ptunnel.httpCompressionRatio", (int)(100d*ratio), 0);
_context.statManager().addRateData("i2ptunnel.httpCompressed", (long)compressed, 0);
_context.statManager().addRateData("i2ptunnel.httpExpanded", (long)expanded, 0);
if (_in != null) {
double compressed = _in.getTotalRead();
double expanded = _in.getTotalExpanded();
ReusableGZIPInputStream.release(_in);
if (compressed > 0 && expanded > 0) {
// only update the stats if we did something
double ratio = compressed/expanded;
_context.statManager().addRateData("i2ptunnel.httpCompressionRatio", (int)(100d*ratio), 0);
_context.statManager().addRateData("i2ptunnel.httpCompressed", (long)compressed, 0);
_context.statManager().addRateData("i2ptunnel.httpExpanded", (long)expanded, 0);
}
}
}
}
/** just a wrapper to provide stats for debugging */
private static class InternalGZIPInputStream extends GZIPInputStream {
public InternalGZIPInputStream(InputStream in) throws IOException {
super(in);
}
public long getTotalRead() {
try {
return super.inf.getTotalIn();
} catch (Exception e) {
return 0;
}
}
public long getTotalExpanded() {
try {
return super.inf.getTotalOut();
} catch (Exception e) {
return 0;
}
}
/**
* From Inflater javadoc:
* Returns the total number of bytes remaining in the input buffer. This can be used to find out
* what bytes still remain in the input buffer after decompression has finished.
*/
public long getRemaining() {
try {
return super.inf.getRemaining();
} catch (Exception e) {
return 0;
}
}
public boolean getFinished() {
try {
return super.inf.finished();
} catch (Exception e) {
return true;
}
}
@Override
public String toString() {
return "Read: " + getTotalRead() + " expanded: " + getTotalExpanded() + " remaining: " + getRemaining() + " finished: " + getFinished();
}
}
@Override
public String toString() {
return super.toString() + ": " + _in;
}
/*******
public static void main(String args[]) {
String simple = "HTTP/1.1 200 OK\n" +

View File

@ -49,6 +49,7 @@ import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import net.i2p.I2PAppContext;
@ -70,16 +71,18 @@ import net.i2p.util.EventDispatcherImpl;
import net.i2p.util.Log;
/**
* An I2PTunnel tracks one or more I2PTunnelTasks and one or more I2PSessions.
* Usually one of each.
*
* Todo: Most events are not listened to elsewhere, so error propagation is poor
*/
public class I2PTunnel implements Logging, EventDispatcher {
private Log _log;
private EventDispatcherImpl _event;
private I2PAppContext _context;
public class I2PTunnel extends EventDispatcherImpl implements Logging {
private final Log _log;
private final I2PAppContext _context;
private static long __tunnelId = 0;
private long _tunnelId;
private Properties _clientOptions;
private final List<I2PSession> _sessions;
private final long _tunnelId;
private final Properties _clientOptions;
private final Set<I2PSession> _sessions;
public static final int PACKET_DELAY = 100;
@ -96,7 +99,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
private static final String nocli_args[] = { "-nocli", "-die"};
private final List tasks = new ArrayList();
private final List<I2PTunnelTask> tasks = new ArrayList();
private int next_task_id = 1;
private final Set listeners = new CopyOnWriteArraySet();
@ -114,14 +117,14 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
public I2PTunnel(String[] args, ConnectionEventListener lsnr) {
super();
_context = I2PAppContext.getGlobalContext(); // new I2PAppContext();
_tunnelId = ++__tunnelId;
_log = _context.logManager().getLog(I2PTunnel.class);
_event = new EventDispatcherImpl();
// as of 0.8.4, include context properties
Properties p = _context.getProperties();
_clientOptions = p;
_sessions = new ArrayList(1);
_sessions = new CopyOnWriteArraySet();
addConnectionEventListener(lsnr);
boolean gui = true;
@ -193,22 +196,17 @@ public class I2PTunnel implements Logging, EventDispatcher {
/** @return non-null */
List<I2PSession> getSessions() {
synchronized (_sessions) {
return new ArrayList(_sessions);
}
}
void addSession(I2PSession session) {
if (session == null) return;
synchronized (_sessions) {
if (!_sessions.contains(session))
_sessions.add(session);
}
_sessions.add(session);
}
void removeSession(I2PSession session) {
if (session == null) return;
synchronized (_sessions) {
_sessions.remove(session);
}
_sessions.remove(session);
}
public Properties getClientOptions() { return _clientOptions; }
@ -218,9 +216,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
if (tsk.isOpen()) {
tsk.setId(next_task_id);
next_task_id++;
synchronized (tasks) {
tasks.add(tsk);
}
tasks.add(tsk);
}
}
@ -693,7 +689,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
" and listening on " + listenHost + ':' + portNum;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("clientTaskId", Integer.valueOf(-1));
@ -769,7 +765,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("httpclientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create an HTTP Proxy connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
" and listening on " + listenHost + ':' + clientPort;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
@ -837,7 +833,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
addtask(task);
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create a CONNECT client connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
" and listening on " + listenHost + ':' + _port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
// Since nothing listens to TaskID events, use this to propagate the error to TunnelController
@ -903,7 +899,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create an IRC client connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
" and listening on " + listenHost + ':' + _port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
@ -957,7 +953,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create a SOCKS Proxy connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
" and listening on " + listenHost + ':' + _port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
@ -1004,7 +1000,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create a SOCKS IRC Proxy connecting to the router at " + host + ':'+ port +
" and listening on " + listenHost + ':' + port;
" and listening on " + listenHost + ':' + _port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
@ -1054,7 +1050,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
String msg = "Invalid I2PTunnel configuration to create a Streamr Client connecting to the router at " + host + ':'+ port +
" and sending to " + _host + ':' + port;
" and sending to " + _host + ':' + _port;
_log.error(getPrefix() + msg, iae);
l.log(msg);
notifyEvent("streamrtunnnelTaskId", Integer.valueOf(-1));
@ -1261,10 +1257,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
*/
public void runQuit(Logging l) {
purgetasks(l);
synchronized (tasks) {
if (tasks.isEmpty()) {
System.exit(0);
}
if (tasks.isEmpty()) {
System.exit(0);
}
l.log("There are running tasks. Try 'list'.");
notifyEvent("quitResult", "error");
@ -1280,11 +1274,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
*/
public void runList(Logging l) {
purgetasks(l);
synchronized (tasks) {
for (int i = 0; i < tasks.size(); i++) {
I2PTunnelTask t = (I2PTunnelTask) tasks.get(i);
l.log("[" + t.getId() + "] " + t.toString());
}
for (I2PTunnelTask t : tasks) {
l.log("[" + t.getId() + "] " + t.toString());
}
notifyEvent("listDone", "done");
}
@ -1313,14 +1304,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
argindex++;
}
if (args[argindex].equalsIgnoreCase("all")) {
List curTasks = null;
synchronized (tasks) {
curTasks = new LinkedList(tasks);
}
boolean error = false;
for (int i = 0; i < curTasks.size(); i++) {
I2PTunnelTask t = (I2PTunnelTask) curTasks.get(i);
for (I2PTunnelTask t : tasks) {
if (!closetask(t, forced, l)) {
notifyEvent("closeResult", "error");
error = true;
@ -1442,9 +1427,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
boolean closed = false;
_log.debug(getPrefix() + "closetask(): looking for task " + num);
synchronized (tasks) {
for (Iterator it = tasks.iterator(); it.hasNext();) {
I2PTunnelTask t = (I2PTunnelTask) it.next();
for (I2PTunnelTask t : tasks) {
int id = t.getId();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "closetask(): parsing task " + id + " (" + t.toString() + ")");
@ -1454,7 +1437,6 @@ public class I2PTunnel implements Logging, EventDispatcher {
} else if (id > num) {
break;
}
}
}
return closed;
}
@ -1482,15 +1464,14 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
*/
private void purgetasks(Logging l) {
synchronized (tasks) {
for (Iterator it = tasks.iterator(); it.hasNext();) {
I2PTunnelTask t = (I2PTunnelTask) it.next();
List<I2PTunnelTask> removed = new ArrayList();
for (I2PTunnelTask t : tasks) {
if (!t.isOpen()) {
_log.debug(getPrefix() + "Purging inactive tunnel: [" + t.getId() + "] " + t.toString());
it.remove();
removed.add(t);
}
}
}
tasks.removeAll(removed);
}
/**
@ -1657,41 +1638,4 @@ public class I2PTunnel implements Logging, EventDispatcher {
public interface ConnectionEventListener {
public void routerDisconnected();
}
/* Required by the EventDispatcher interface */
public EventDispatcher getEventDispatcher() {
return _event;
}
public void attachEventDispatcher(EventDispatcher e) {
_event.attachEventDispatcher(e.getEventDispatcher());
}
public void detachEventDispatcher(EventDispatcher e) {
_event.detachEventDispatcher(e.getEventDispatcher());
}
public void notifyEvent(String e, Object a) {
_event.notifyEvent(e, a);
}
public Object getEventValue(String n) {
return _event.getEventValue(n);
}
public Set getEvents() {
return _event.getEvents();
}
public void ignoreEvents() {
_event.ignoreEvents();
}
public void unIgnoreEvents() {
_event.unIgnoreEvents();
}
public Object waitEventValue(String n) {
return _event.waitEventValue(n);
}
}

View File

@ -51,7 +51,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
protected long _clientId;
protected final Object sockLock = new Object(); // Guards sockMgr and mySockets
protected I2PSocketManager sockMgr; // should be final and use a factory. LINT
protected List mySockets = new ArrayList();
protected final List<I2PSocket> mySockets = new ArrayList();
protected boolean _ownDest;
protected Destination dest = null;
@ -59,7 +59,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private boolean listenerReady = false;
private ServerSocket ss;
protected ServerSocket ss;
private final Object startLock = new Object();
private boolean startRunning = false;
@ -83,12 +83,17 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* Extending classes may use it for other purposes.
* Not for use by servers, as there is no limit on threads.
*/
static final Executor _executor;
private static volatile ThreadPoolExecutor _executor;
private static int _executorThreadCount;
static {
_executor = new CustomThreadPoolExecutor();
}
private static final Object _executorLock = new Object();
/**
* This constructor always starts the tunnel (ignoring the i2cp.delayOpen option).
* It is used to add a client to an existing socket manager.
*
* @param localPort if 0, use any port, get actual port selected with getLocalPort()
* @param sktMgr the existing socket manager
*/
public I2PTunnelClientBase(int localPort, Logging l, I2PSocketManager sktMgr,
I2PTunnel tunnel, EventDispatcher notifyThis, long clientId )
throws IllegalArgumentException {
@ -107,8 +112,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
_context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_log = _context.logManager().getLog(getClass());
synchronized (_executorLock) {
if (_executor == null)
_executor = new CustomThreadPoolExecutor();
}
Thread t = new I2PAppThread(this, "Client " + tunnel.listenHost + ':' + localPort);
listenerReady = false;
t.start();
open = true;
synchronized (this) {
@ -130,6 +139,14 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
/**
* The main constructor.
* This may take a LONG time if building and starting a new manager.
*
* @param localPort if 0, use any port, get actual port selected with getLocalPort()
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we can't create a socketManager
*/
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
EventDispatcher notifyThis, String handlerName,
I2PTunnel tunnel) throws IllegalArgumentException {
@ -137,10 +154,14 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
/**
* @param pkf null to generate a transient key
* Use this to build a client with a persistent private key.
* This may take a LONG time if building and starting a new manager.
*
* @param localPort if 0, use any port, get actual port selected with getLocalPort()
* @param pkf Path to the private key file, or null to generate a transient key
*
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
* badly that we can't create a socketManager
*/
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
EventDispatcher notifyThis, String handlerName,
@ -160,6 +181,11 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
_context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_log = _context.logManager().getLog(getClass());
synchronized (_executorLock) {
if (_executor == null)
_executor = new CustomThreadPoolExecutor();
}
// normalize path so we can find it
if (pkf != null) {
File keyFile = new File(pkf);
@ -170,7 +196,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
// no need to load the netDb with leaseSets for destinations that will never
// be looked up
tunnel.getClientOptions().setProperty("i2cp.dontPublishLeaseSet", "true");
boolean dccEnabled = (this instanceof I2PTunnelIRCClient) &&
Boolean.valueOf(tunnel.getClientOptions().getProperty(I2PTunnelIRCClient.PROP_DCC)).booleanValue();
if (!dccEnabled)
tunnel.getClientOptions().setProperty("i2cp.dontPublishLeaseSet", "true");
boolean openNow = !Boolean.valueOf(tunnel.getClientOptions().getProperty("i2cp.delayOpen")).booleanValue();
if (openNow) {
@ -183,17 +212,17 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
}
}
if (sockMgr == null) {
l.log("Invalid I2CP configuration");
throw new IllegalArgumentException("Socket manager could not be created");
}
// can't be null unless we limit the loop above
//if (sockMgr == null) {
// l.log("Invalid I2CP configuration");
// throw new IllegalArgumentException("Socket manager could not be created");
//}
l.log("Tunnels ready for client: " + handlerName);
} // else delay creating session until createI2PSocket() is called
Thread t = new I2PAppThread(this);
t.setName("Client " + _clientId);
listenerReady = false;
t.start();
open = true;
synchronized (this) {
@ -219,7 +248,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
/**
* Sets the this.sockMgr field if it is null, or if we want a new one
* Sets the this.sockMgr field if it is null, or if we want a new one.
* This may take a LONG time if building a new manager.
*
* We need a socket manager before getDefaultOptions() and most other things
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
@ -258,27 +288,33 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
/**
* this is ONLY for shared clients
* This is ONLY for shared clients.
* This may take a LONG time if building a new manager.
*
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected synchronized I2PSocketManager getSocketManager() {
protected I2PSocketManager getSocketManager() {
return getSocketManager(getTunnel(), this.privKeyFile);
}
/**
* this is ONLY for shared clients
* This is ONLY for shared clients.
* This may take a LONG time if building a new manager.
*
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
protected static I2PSocketManager getSocketManager(I2PTunnel tunnel) {
return getSocketManager(tunnel, null);
}
/**
* this is ONLY for shared clients
* This is ONLY for shared clients.
* This may take a LONG time if building a new manager.
*
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
@ -293,6 +329,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since the old one closed [s=" + s + "]");
if (s != null)
tunnel.removeSession(s);
// We could be here a LONG time, holding the lock
socketManager = buildSocketManager(tunnel, pkf);
} else {
if (_log.shouldLog(Log.INFO))
@ -307,6 +344,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
/**
* This may take a LONG time.
*
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
@ -315,6 +354,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
return buildSocketManager(getTunnel(), this.privKeyFile, this.l);
}
/**
* This may take a LONG time.
*
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
@ -327,6 +368,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private static final int MAX_RETRIES = 4;
/**
* This may take a LONG time.
*
* @param pkf absolute path or null
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
@ -337,6 +380,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
/**
* This may take a LONG time.
*
* @param pkf absolute path or null
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
@ -357,7 +402,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
I2PSocketManager sockManager = null;
// Todo: Can't stop a tunnel from the UI while it's in this loop (no session yet)
// FIXME: Can't stop a tunnel from the UI while it's in this loop (no session yet)
int retries = 0;
while (sockManager == null) {
if (pkf != null) {
@ -512,7 +557,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
if (localPort == 0) {
localPort = ss.getLocalPort();
}
notifyEvent("clientLocalPort", new Integer(ss.getLocalPort()));
notifyEvent("clientLocalPort", Integer.valueOf(ss.getLocalPort()));
// duplicates message in constructor
//l.log("Listening for clients on port " + localPort + " of " + getTunnel().listenHost);
@ -551,6 +596,30 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
/**
* @return may be null if no class has been instantiated
* @since 0.8.8
*/
static ThreadPoolExecutor getClientExecutor() {
return _executor;
}
/**
* @since 0.8.8
*/
static void killClientExecutor() {
synchronized (_executorLock) {
if (_executor != null) {
_executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
_executor.shutdownNow();
_executor = null;
}
// kill the shared client, so that on restart in android
// we won't latch onto the old one
socketManager = null;
}
}
/**
* Manage the connection just opened on the specified socket
*
@ -558,8 +627,16 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
*/
protected void manageConnection(Socket s) {
if (s == null) return;
ThreadPoolExecutor tpe = _executor;
if (tpe == null) {
_log.error("No executor for socket!");
try {
s.close();
} catch (IOException ioe) {}
return;
}
try {
_executor.execute(new BlockingRunner(s));
tpe.execute(new BlockingRunner(s));
} catch (RejectedExecutionException ree) {
// should never happen, we have an unbounded pool and never stop the executor
try {
@ -610,11 +687,11 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
synchronized (sockLock) {
if (sockMgr != null) {
mySockets.retainAll(sockMgr.listSockets());
if (!forced && mySockets.size() != 0) {
l.log("There are still active connections!");
if ((!forced) && (!mySockets.isEmpty())) {
l.log("Not closing, there are still active connections!");
_log.debug("can't close: there are still active connections!");
for (Iterator it = mySockets.iterator(); it.hasNext();) {
l.log("->" + it.next());
for (I2PSocket s : mySockets) {
l.log(" -> " + s.toString());
}
return false;
}
@ -630,12 +707,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
try {
if (ss != null) ss.close();
} catch (IOException ex) {
ex.printStackTrace();
if (_log.shouldLog(Log.WARN))
_log.warn("error closing", ex);
return false;
}
//l.log("Client closed.");
}
return true;
}

View File

@ -305,7 +305,8 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
else
response = SUCCESS_RESPONSE;
Runnable onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
I2PTunnelRunner runner = new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout);
// starts itself
new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout);
} catch (SocketException ex) {
_log.info(getPrefix(requestId) + "Error trying to connect", ex);
handleConnectClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);

View File

@ -18,18 +18,24 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PSession;
import net.i2p.client.naming.NamingService;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Base32;
import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.util.EventDispatcher;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
@ -62,7 +68,16 @@ import net.i2p.util.Translate;
*/
public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runnable {
private HashMap addressHelpers = new HashMap();
/**
* Map of host name to base64 destination for destinations collected
* via address helper links
*/
private final ConcurrentHashMap<String, String> addressHelpers = new ConcurrentHashMap(8);
/**
* Used to protect actions via http://proxy.i2p/
*/
private final String _proxyNonce;
/**
* These are backups if the xxx.ht error page is missing.
@ -130,6 +145,29 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
"or naming one of them differently.<p>")
.getBytes();
private final static byte[] ERR_AHELPER_NOTFOUND =
("HTTP/1.1 404 Not Found\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"\r\n"+
"<html><body><H1>I2P ERROR: Helper key not resolvable.</H1>"+
"The helper key you put for i2paddresshelper= is not resolvable. "+
"It seems to be garbage data, or a mistyped b32. Check your URL "+
"to try and fix the helper key to be either a b32 or a base64.")
.getBytes();
private final static byte[] ERR_AHELPER_NEW =
("HTTP/1.1 409 New Address\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"\r\n"+
"<html><body><H1>New Host Name with Address Helper</H1>"+
"The address helper link you followed is for a new host name that is not in your address book. " +
"You may either save the destination for this host name to your address book, or remember it only until your router restarts. " +
"If you save it to your address book, you will not see this message again. " +
"If you do not wish to visit this host, click the \"back\" button on your browser.")
.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"+
@ -160,8 +198,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
"This proxy is configured to require authentication.<BR>")
.getBytes();
/**
* This constructor always starts the tunnel (ignoring the i2cp.delayOpen option).
* It is used to add a client to an existing socket manager.
*
* @param sockMgr the existing socket manager
*/
public I2PTunnelHTTPClient(int localPort, Logging l, I2PSocketManager sockMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) {
super(localPort, l, sockMgr, tunnel, notifyThis, clientId);
_proxyNonce = Long.toString(_context.random().nextLong());
// proxyList = new ArrayList();
setName("HTTP Proxy on " + getTunnel().listenHost + ':' + localPort);
@ -177,6 +222,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
String wwwProxy, EventDispatcher notifyThis,
I2PTunnel tunnel) throws IllegalArgumentException {
super(localPort, ownDest, l, notifyThis, "HTTP Proxy on " + tunnel.listenHost + ':' + localPort + " #" + (++__clientId), tunnel);
_proxyNonce = Long.toString(_context.random().nextLong());
//proxyList = new ArrayList(); // We won't use outside of i2p
if (waitEventValue("openBaseClientResult").equals("error")) {
@ -258,12 +304,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
return rv;
}
private static final String LOCAL_SERVER = "proxy.i2p";
private static final boolean DEFAULT_GZIP = true;
// all default to false
/** 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";
public static final String PROP_DISABLE_HELPER = "i2ptunnel.httpclient.disableAddressHelper";
protected void clientConnectionRun(Socket s) {
InputStream in = null;
@ -278,7 +326,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
InputReader reader = new InputReader(s.getInputStream());
String line, method = null, protocol = null, host = null, destination = null;
StringBuilder newRequest = new StringBuilder();
int ahelper = 0;
boolean ahelperPresent = false;
boolean ahelperNew = false;
String ahelperKey = null;
String userAgent = null;
String authorization = null;
while ((line = reader.readLine(method)) != null) {
line = line.trim();
@ -334,11 +385,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
protocol = request.substring(0, pos + 2);
request = request.substring(pos + 2);
// "foo.i2p/bar/baz HTTP/1.1", with any i2paddresshelper parameter removed
targetRequest = request;
// pos is the start of the path
pos = request.indexOf("/");
if (pos == -1) {
//pos = request.length();
method = null;
break;
}
@ -380,21 +433,20 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
destination = host;
host = getHostName(destination);
line = method + ' ' + request.substring(pos);
} else if (host.toLowerCase().equals("proxy.i2p")) {
} else if (host.toLowerCase().equals(LOCAL_SERVER)) {
// so we don't do any naming service lookups
destination = host;
usingInternalServer = true;
} else if (host.toLowerCase().endsWith(".i2p")) {
// Destination gets the host name
destination = host;
// Host becomes the destination key
// Host becomes the destination's "{b32}.b32.i2p" string, or "i2p" on lookup failure
host = getHostName(destination);
int pos2;
if ((pos2 = request.indexOf("?")) != -1) {
// Try to find an address helper in the fragments
// and split the request into it's component parts for rebuilding later
String ahelperKey = null;
boolean ahelperConflict = false;
String fragments = request.substring(pos2 + 1);
@ -404,6 +456,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
String urlEncoding = "";
fragments = fragments.substring(0, pos2);
String initialFragments = fragments;
// FIXME split on ';' also
fragments = fragments + "&";
String fragment;
while(fragments.length() > 0) {
@ -412,35 +465,65 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
fragments = fragments.substring(pos2 + 1);
// Fragment looks like addresshelper key
if (fragment.startsWith("i2paddresshelper=")) {
if (fragment.startsWith("i2paddresshelper=") &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
pos2 = fragment.indexOf("=");
ahelperKey = fragment.substring(pos2 + 1);
// Key contains data, lets not ignore it
if (ahelperKey != null) {
// ahelperKey will be validated later
if(ahelperKey.endsWith(".i2p")) {
// allow i2paddresshelper=<b32>.b32.i2p syntax.
/*
also i2paddresshelper=name.i2p for aliases
i.e. on your eepsite put
<a href="?i2paddresshelper=name.i2p">This is the name I want to be called.</a>
*/
Destination dest = _context.namingService().lookup(ahelperKey);
if(dest==null) {
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Could not find destination for "+ahelperKey);
byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
out.write(header);
out.write(("<p>" + _("This seems to be a bad destination:") + " " + ahelperKey + " " + _("i2paddresshelper cannot help you with a destination like that!") + "</p>").getBytes("UTF-8"));
writeFooter(out);
// XXX: should closeSocket(s) be in a finally block?
closeSocket(s);
return;
}
ahelperKey = dest.toBase64();
}
// Host resolvable only with addresshelper
if ( (host == null) || ("i2p".equals(host)) )
{
// Cannot check, use addresshelper key
addressHelpers.put(destination,ahelperKey);
} else {
// Host resolvable from database, verify addresshelper key
// Silently bypass correct keys, otherwise alert
String destB64 = null;
Destination _dest = _context.namingService().lookup(host);
if (_dest != null)
destB64 = _dest.toBase64();
if (destB64 != null && !destB64.equals(ahelperKey))
{
ahelperPresent = true;
// ahelperKey will be validated later
if (host == null || "i2p".equals(host)) {
// Host lookup failed - resolvable only with addresshelper
// Store in local HashMap unless there is conflict
String old = addressHelpers.putIfAbsent(destination.toLowerCase(), ahelperKey);
ahelperNew = old == null;
if ((!ahelperNew) && !old.equals(ahelperKey)) {
// Conflict: handle when URL reconstruction done
ahelperConflict = true;
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination + "], trusted key [" + destB64 + "], specified key [" + ahelperKey + "].");
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
"], trusted key [" + old + "], specified key [" + ahelperKey + "].");
}
} else {
// If the host is resolvable from database, verify addresshelper key
// Silently bypass correct keys, otherwise alert
Destination hostDest = _context.namingService().lookup(destination);
if (hostDest != null) {
String destB64 = hostDest.toBase64();
if (destB64 != null && !destB64.equals(ahelperKey)) {
// Conflict: handle when URL reconstruction done
ahelperConflict = true;
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
"], trusted key [" + destB64 + "], specified key [" + ahelperKey + "].");
}
}
}
}
} // ahelperKey
} else {
// Other fragments, just pass along
// Append each fragment to urlEncoding
@ -453,11 +536,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
}
// Reconstruct the request minus the i2paddresshelper GET var
request = uriPath + urlEncoding + " " + protocolVersion;
targetRequest = request;
// Did addresshelper key conflict?
if (ahelperConflict)
{
if (ahelperConflict) {
if (out != null) {
// convert ahelperKey to b32
String alias = getHostName(ahelperKey);
@ -472,23 +554,22 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
out.write(header);
out.write(_("To visit the destination in your host database, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, click <a href=\"{1}\">here</a>.", trustedURL, conflictURL).getBytes("UTF-8"));
out.write(("<p></div>").getBytes());
out.write(("</p></div>").getBytes());
writeFooter(out);
}
}
s.close();
return;
}
}
} // end query processing
String addressHelper = (String) addressHelpers.get(destination);
if (addressHelper != null) {
destination = addressHelper;
host = getHostName(destination);
ahelper = 1;
}
String addressHelper = addressHelpers.get(destination);
if (addressHelper != null)
host = getHostName(addressHelper);
line = method + " " + request.substring(pos);
// end of (host endsWith(".i2p"))
} else if (host.toLowerCase().equals("localhost") || host.equals("127.0.0.1") ||
host.startsWith("192.168.")) {
// if somebody is trying to get to 192.168.example.com, oh well
@ -584,10 +665,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
line = "Host: " + host;
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()) {
line = null;
continue;
} else if (lowercaseLine.startsWith("user-agent: ")) {
// save for deciding whether to offer address book form
userAgent = lowercaseLine.substring(12);
if (!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue()) {
line = null;
continue;
}
} else if (lowercaseLine.startsWith("accept")) {
// strip the accept-blah headers, as they vary dramatically from
// browser to browser
@ -687,15 +771,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
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
// Allow without authorization
if (usingInternalServer) {
serveLocalFile(out, method, targetRequest);
s.close();
return;
}
// Authorization
if (!authorize(s, requestId, authorization)) {
if (_log.shouldLog(Log.WARN)) {
@ -705,19 +780,56 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
_log.warn(getPrefix(requestId) + "Auth required, sending 407");
}
out.write(getErrorPage("auth", ERR_AUTH));
writeFooter(out);
s.close();
return;
}
// Serve local proxy files (images, css linked from error pages)
// Ignore all the headers
if (usingInternalServer) {
// disable the add form if address helper is disabled
if (targetRequest.startsWith(LOCAL_SERVER + "/add?") &&
Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
out.write(ERR_HELPER_DISABLED);
} else {
serveLocalFile(out, method, targetRequest, _proxyNonce);
}
s.close();
return;
}
// LOOKUP
// If the host is "i2p", the getHostName() lookup failed, don't try to
// look it up again as the naming service does not do negative caching
// so it will be slow.
Destination clientDest;
if ("i2p".equals(host))
Destination clientDest = null;
String addressHelper = addressHelpers.get(destination.toLowerCase());
if (addressHelper != null) {
clientDest = _context.namingService().lookup(addressHelper);
// remove bad entries
if (clientDest == null)
addressHelpers.remove(destination.toLowerCase());
} else if ("i2p".equals(host)) {
clientDest = null;
else
} else if (destination.length() == 60 && destination.toLowerCase().endsWith(".b32.i2p")) {
// use existing session to look up for efficiency
verifySocketManager();
I2PSession sess = sockMgr.getSession();
if (sess != null && !sess.isClosed()) {
byte[] hData = Base32.decode(destination.substring(0, 52));
if (hData != null) {
if (_log.shouldLog(Log.INFO))
_log.info("lookup in-session " + destination);
Hash hash = Hash.create(hData);
clientDest = sess.lookupDest(hash, 20*1000);
}
} else {
clientDest = _context.namingService().lookup(destination);
}
} else {
clientDest = _context.namingService().lookup(destination);
}
if (clientDest == null) {
//l.log("Could not resolve " + destination + ".");
@ -727,9 +839,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
String jumpServers = null;
if (usingWWWProxy)
header = getErrorPage("dnfp", ERR_DESTINATION_UNKNOWN);
else if(ahelper != 0)
else if (ahelperPresent)
header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
else if (destination.length() == 60 && destination.endsWith(".b32.i2p"))
else if (destination.length() == 60 && destination.toLowerCase().endsWith(".b32.i2p"))
header = getErrorPage("dnf", ERR_DESTINATION_UNKNOWN);
else {
header = getErrorPage("dnfh", ERR_DESTINATION_UNKNOWN);
@ -741,7 +853,35 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
s.close();
return;
}
String remoteID;
// Address helper response form
// This will only load once - the second time it won't be "new"
// Don't do this for eepget, which uses a user-agent of "Wget"
if (ahelperNew && "GET".equals(method) &&
(userAgent == null || !userAgent.startsWith("Wget")) &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
writeHelperSaveForm(out, destination, ahelperKey, protocol + targetRequest);
s.close();
return;
}
// Redirect to non-addresshelper URL to not clog the browser address bar
// and not pass the parameter to the eepsite.
// This also prevents the not-found error page from looking bad
// Syndie can't handle a redirect of a POST
if (ahelperPresent && !"POST".equals(method)) {
String uri = protocol + targetRequest;
int spc = uri.indexOf(" ");
if (spc >= 0)
uri = uri.substring(0, spc);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Auto redirecting to " + uri);
out.write(("HTTP/1.1 301 Address Helper Accepted\r\n"+
"Location: " + uri + "\r\n"+
"\r\n").getBytes("UTF-8"));
s.close();
return;
}
Properties opts = new Properties();
//opts.setProperty("i2p.streaming.inactivityTimeout", ""+120*1000);
@ -779,6 +919,38 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
}
}
/** @since 0.8.7 */
private void writeHelperSaveForm(OutputStream out, String destination, String ahelperKey, String targetRequest) throws IOException {
if (out == null)
return;
// strip HTTP/1.1
int protopos = targetRequest.indexOf(" ");
if (protopos >= 0)
targetRequest = targetRequest.substring(0, protopos);
byte[] header = getErrorPage("ahelper-new", ERR_AHELPER_NEW);
out.write(header);
out.write(("<table><tr><td class=\"mediumtags\" align=\"right\">" + _("Host") + "</td><td class=\"mediumtags\">" + destination + "</td></tr>\n" +
"<tr><td class=\"mediumtags\" align=\"right\">" + _("Destination") + "</td><td>" +
"<textarea rows=\"1\" style=\"height: 4em; min-width: 0; min-height: 0;\" cols=\"70\" wrap=\"off\" readonly=\"readonly\" >" +
ahelperKey + "</textarea></td></tr></table>\n" +
"<hr><div class=\"formaction\">"+
"<form method=\"GET\" action=\"" + targetRequest + "\">" +
"<button type=\"submit\">" + _("Continue to {0} without saving", destination) + "</button>" +
"</form>\n<form method=\"GET\" action=\"http://" + LOCAL_SERVER + "/add\">" +
"<input type=\"hidden\" name=\"host\" value=\"" + destination + "\">\n" +
"<input type=\"hidden\" name=\"dest\" value=\"" + ahelperKey + "\">\n" +
"<input type=\"hidden\" name=\"nonce\" value=\"" + _proxyNonce + "\">\n" +
"<button type=\"submit\" name=\"router\" value=\"router\">" + _("Save {0} to router address book and continue to eepsite", destination) + "</button><br>\n").getBytes("UTF-8"));
if (_context.namingService().getName().equals("BlockfileNamingService")) {
// only blockfile supports multiple books
out.write(("<button type=\"submit\" name=\"master\" value=\"master\">" + _("Save {0} to master address book and continue to eepsite", destination) + "</button><br>\n").getBytes("UTF-8"));
out.write(("<button type=\"submit\" name=\"private\" value=\"private\">" + _("Save {0} to private address book and continue to eepsite", destination) + "</button>\n").getBytes("UTF-8"));
}
out.write(("<input type=\"hidden\" name=\"url\" value=\"" + targetRequest + "\">\n" +
"</form></div></div>").getBytes());
writeFooter(out);
}
/**
* Read the first line unbuffered.
* After that, switch to a BufferedReader, unless the method is "POST".
@ -915,7 +1087,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
out.write(errMessage);
if (targetRequest != null) {
int protopos = targetRequest.indexOf(" ");
String uri = null;
String uri;
if (protopos >= 0)
uri = targetRequest.substring(0, protopos);
else
@ -1022,6 +1194,20 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
"HTTP Proxy local file not found")
.getBytes();
private final static byte[] ERR_ADD =
("HTTP/1.1 409 Bad\r\n"+
"Content-Type: text/plain\r\n"+
"\r\n"+
"Add to addressbook failed - bad parameters")
.getBytes();
private final static byte[] ERR_HELPER_DISABLED =
("HTTP/1.1 403 Disabled\r\n"+
"Content-Type: text/plain\r\n"+
"\r\n"+
"Address helpers disabled")
.getBytes();
/**
* Very simple web server.
*
@ -1043,9 +1229,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
*
* @param targetRequest "proxy.i2p/themes/foo.png HTTP/1.1"
*/
private static void serveLocalFile(OutputStream out, String method, String targetRequest) {
private static void serveLocalFile(OutputStream out, String method, String targetRequest, String proxyNonce) {
//System.err.println("targetRequest: \"" + targetRequest + "\"");
// a home page message for the curious...
if (targetRequest.startsWith("proxy.i2p/ ")) {
if (targetRequest.startsWith(LOCAL_SERVER + "/ ")) {
try {
out.write(("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: max-age=86400\r\n\r\nI2P HTTP proxy OK").getBytes());
out.flush();
@ -1053,13 +1240,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
return;
}
if ((method.equals("GET") || method.equals("HEAD")) &&
targetRequest.startsWith("proxy.i2p/themes/") &&
targetRequest.startsWith(LOCAL_SERVER + "/themes/") &&
!targetRequest.contains("..")) {
int space = targetRequest.indexOf(' ');
String filename = null;
try {
filename = targetRequest.substring(17, space); // "proxy.i2p/themes/".length
} catch (IndexOutOfBoundsException ioobe) {}
filename = targetRequest.substring(LOCAL_SERVER.length() + 8, space); // "/themes/".length
} catch (IndexOutOfBoundsException ioobe) {
return;
}
// theme hack
if (filename.startsWith("console/default/"))
filename = filename.replaceFirst("default", I2PAppContext.getGlobalContext().getProperty("routerconsole.theme", "light"));
@ -1081,9 +1270,65 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
out.write(type.getBytes());
out.write("\r\nCache-Control: max-age=86400\r\n\r\n".getBytes());
FileUtil.readFile(filename, themesDir.getAbsolutePath(), out);
} catch (IOException ioe) {}
return;
}
}
// Add to addressbook (form submit)
// Parameters are url, host, dest, nonce, and master | router | private.
// Do the add and redirect.
if (targetRequest.startsWith(LOCAL_SERVER + "/add?")) {
int spc = targetRequest.indexOf(' ');
String query = targetRequest.substring(LOCAL_SERVER.length() + 5, spc); // "/add?".length()
Map<String, String> opts = new HashMap(8);
StringTokenizer tok = new StringTokenizer(query, "=&;");
while (tok.hasMoreTokens()) {
String k = tok.nextToken();
if (!tok.hasMoreTokens())
break;
String v = tok.nextToken();
opts.put(decode(k), decode(v));
}
String url = opts.get("url");
String host = opts.get("host");
String b64Dest = opts.get("dest");
String nonce = opts.get("nonce");
String book = "privatehosts.txt";
if (opts.get("master") != null)
book = "userhosts.txt";
else if (opts.get("router") != null)
book = "hosts.txt";
Destination dest = null;
if (b64Dest != null) {
try {
dest = new Destination(b64Dest);
} catch (DataFormatException dfe) {
System.err.println("Bad dest to save?" + b64Dest);
}
}
//System.err.println("url : \"" + url + "\"");
//System.err.println("host : \"" + host + "\"");
//System.err.println("b64dest : \"" + b64Dest + "\"");
//System.err.println("book : \"" + book + "\"");
//System.err.println("nonce : \"" + nonce + "\"");
if (proxyNonce.equals(nonce) && url != null && host != null && dest != null) {
try {
NamingService ns = I2PAppContext.getGlobalContext().namingService();
Properties nsOptions = new Properties();
nsOptions.setProperty("list", book);
nsOptions.setProperty("s", _("Added via address helper"));
boolean success = ns.put(host, dest, nsOptions);
writeRedirectPage(out, success, host, book, url);
return;
} catch (IOException ioe) {}
}
try {
out.write(ERR_ADD);
out.flush();
} catch (IOException ioe) {}
return;
}
try {
out.write(ERR_404);
@ -1091,16 +1336,72 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
} catch (IOException ioe) {}
}
/** @since 0.8.7 */
private static void writeRedirectPage(OutputStream out, boolean success, String host, String book, String url) throws IOException {
out.write(("HTTP/1.1 200 OK\r\n"+
"Content-Type: text/html; charset=UTF-8\r\n"+
"\r\n"+
"<html><head>"+
"<title>" + _("Redirecting to {0}", host) + "</title>\n" +
"<link rel=\"shortcut icon\" href=\"http://proxy.i2p/themes/console/images/favicon.ico\" >\n" +
"<link href=\"http://proxy.i2p/themes/console/default/console.css\" rel=\"stylesheet\" type=\"text/css\" >\n" +
"<meta http-equiv=\"Refresh\" content=\"1; url=" + url + "\">\n" +
"</head><body>\n" +
"<div class=logo>\n" +
"<a href=\"http://127.0.0.1:7657/\" title=\"" + _("Router Console") + "\"><img src=\"http://proxy.i2p/themes/console/images/i2plogo.png\" alt=\"I2P Router Console\" border=\"0\"></a><hr>\n" +
"<a href=\"http://127.0.0.1:7657/config\">" + _("Configuration") + "</a> <a href=\"http://127.0.0.1:7657/help.jsp\">" + _("Help") + "</a> <a href=\"http://127.0.0.1:7657/susidns/index.jsp\">" + _("Addressbook") + "</a>\n" +
"</div>" +
"<div class=warning id=warning>\n" +
"<h3>" +
(success ?
_("Saved {0} to the {1} addressbook, redirecting now.", host, book) :
_("Failed to save {0} to the {1} addressbook, redirecting now.", host, book)) +
"</h3>\n<p><a href=\"" + url + "\">" +
_("Click here if you are not redirected automatically.") +
"</a></p></div>").getBytes("UTF-8"));
writeFooter(out);
out.flush();
}
/**
* Decode %xx encoding
* @since 0.8.7
*/
private static String decode(String s) {
if (!s.contains("%"))
return s;
StringBuilder buf = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c != '%') {
buf.append(c);
} else {
try {
buf.append((char) Integer.parseInt(s.substring(++i, (++i) + 1), 16));
} catch (IndexOutOfBoundsException ioobe) {
break;
} catch (NumberFormatException nfe) {
break;
}
}
}
return buf.toString();
}
private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
/** lang in routerconsole.lang property, else current locale */
public static String _(String key) {
protected static String _(String key) {
return Translate.getString(key, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
}
/** {0} */
protected static String _(String key, Object o) {
return Translate.getString(key, o, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
}
/** {0} and {1} */
public static String _(String key, Object o, Object o2) {
protected static String _(String key, Object o, Object o2) {
return Translate.getString(key, o, o2, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
}

View File

@ -66,6 +66,12 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
_proxyList = new ArrayList(4);
}
/**
* This constructor always starts the tunnel (ignoring the i2cp.delayOpen option).
* It is used to add a client to an existing socket manager.
*
* @param sktMgr the existing socket manager
*/
public I2PTunnelHTTPClientBase(int localPort, Logging l, I2PSocketManager sktMgr,
I2PTunnel tunnel, EventDispatcher notifyThis, long clientId )
throws IllegalArgumentException {

View File

@ -24,10 +24,9 @@ import net.i2p.util.Log;
*
*/
public class I2PTunnelHTTPClientRunner extends I2PTunnelRunner {
private Log _log;
public I2PTunnelHTTPClientRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData, List sockList, Runnable onTimeout) {
public I2PTunnelHTTPClientRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData,
List<I2PSocket> sockList, Runnable onTimeout) {
super(s, i2ps, slock, initialI2PData, sockList, onTimeout);
_log = I2PAppContext.getGlobalContext().logManager().getLog(I2PTunnelHTTPClientRunner.class);
}
@Override
@ -36,10 +35,22 @@ public class I2PTunnelHTTPClientRunner extends I2PTunnelRunner {
return new HTTPResponseOutputStream(raw);
}
/**
* Why is this overridden?
* Why flush in super but not here?
* Why do things in different order than in super?
*/
@Override
protected void close(OutputStream out, InputStream in, OutputStream i2pout, InputStream i2pin, Socket s, I2PSocket i2ps, Thread t1, Thread t2) throws InterruptedException, IOException {
protected void close(OutputStream out, InputStream in, OutputStream i2pout, InputStream i2pin,
Socket s, I2PSocket i2ps, Thread t1, Thread t2) throws InterruptedException {
try {
i2pin.close();
} catch (IOException ioe) {
// ignore
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unable to close the i2p socket input stream: " + i2pin, ioe);
}
try {
i2pout.close();
} catch (IOException ioe) {
// ignore
@ -48,14 +59,28 @@ public class I2PTunnelHTTPClientRunner extends I2PTunnelRunner {
}
try {
in.close();
} catch (IOException ioe) {
// ignore
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unable to close the browser input stream: " + in, ioe);
}
try {
out.close();
} catch (IOException ioe) {
// ignore
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unable to close the browser output stream: " + out, ioe);
}
i2ps.close();
s.close();
try {
i2ps.close();
} catch (IOException ioe) {
// ignore
}
try {
s.close();
} catch (IOException ioe) {
// ignore
}
t1.join(30*1000);
t2.join(30*1000);
}

View File

@ -116,11 +116,6 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
// according to rfc2616 s14.3, this *should* force identity, even if
// "identity;q=1, *;q=0" didn't.
setEntry(headers, "Accept-encoding", "");
String modifiedHeader = formatHeaders(headers, command);
//String modifiedHeader = getModifiedHeader(socket);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Modified header: [" + modifiedHeader + "]");
socket.setReadTimeout(readTimeout);
Socket s = new Socket(remoteHost, remotePort);
@ -138,9 +133,15 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
if (_log.shouldLog(Log.INFO))
_log.info("HTTP server encoding header: " + enc + "/" + altEnc);
boolean useGZIP = ( (enc != null) && (enc.indexOf("x-i2p-gzip") >= 0) );
if ( (!useGZIP) && (altEnc != null) && (altEnc.indexOf("x-i2p-gzip") >= 0) )
useGZIP = true;
boolean alt = (altEnc != null) && (altEnc.indexOf("x-i2p-gzip") >= 0);
boolean useGZIP = alt || ( (enc != null) && (enc.indexOf("x-i2p-gzip") >= 0) );
// Don't pass this on, outproxies should strip so I2P traffic isn't so obvious but they probably don't
if (alt)
headers.remove("X-Accept-encoding");
String modifiedHeader = formatHeaders(headers, command);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Modified header: [" + modifiedHeader + "]");
if (allowGZIP && useGZIP) {
I2PAppThread req = new I2PAppThread(
@ -302,19 +303,58 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
}
/**
* This plus a typ. HTTP response header will fit into a 1730-byte streaming message.
*/
private static final int MIN_TO_COMPRESS = 1300;
private static class CompressedResponseOutputStream extends HTTPResponseOutputStream {
private InternalGZIPOutputStream _gzipOut;
public CompressedResponseOutputStream(OutputStream o) {
super(o);
_dataExpected = -1;
}
/**
* Overridden to peek at response code. Always returns line.
*/
@Override
protected boolean shouldCompress() { return true; }
protected String filterResponseLine(String line) {
String[] s = line.split(" ", 3);
if (s.length > 1 &&
(s[1].startsWith("3") || s[1].startsWith("5")))
_dataExpected = 0;
return line;
}
/**
* Don't compress small responses or images.
* Compression is inline but decompression on the client side
* creates a new thread.
*/
@Override
protected boolean shouldCompress() {
return (_dataExpected < 0 || _dataExpected >= MIN_TO_COMPRESS) &&
(_contentType == null ||
((!_contentType.startsWith("audio/")) &&
(!_contentType.startsWith("image/")) &&
(!_contentType.startsWith("video/")) &&
(!_contentType.equals("application/compress")) &&
(!_contentType.equals("application/bzip2")) &&
(!_contentType.equals("application/gzip")) &&
(!_contentType.equals("application/x-bzip")) &&
(!_contentType.equals("application/x-bzip2")) &&
(!_contentType.equals("application/x-gzip")) &&
(!_contentType.equals("application/zip"))));
}
@Override
protected void finishHeaders() throws IOException {
//if (_log.shouldLog(Log.INFO))
// _log.info("Including x-i2p-gzip as the content encoding in the response");
out.write("Content-encoding: x-i2p-gzip\r\n".getBytes());
if (shouldCompress())
out.write("Content-encoding: x-i2p-gzip\r\n".getBytes());
super.finishHeaders();
}
@ -323,9 +363,12 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
//if (_log.shouldLog(Log.INFO))
// _log.info("Beginning compression processing");
//out.flush();
_gzipOut = new InternalGZIPOutputStream(out);
out = _gzipOut;
if (shouldCompress()) {
_gzipOut = new InternalGZIPOutputStream(out);
out = _gzipOut;
}
}
public long getTotalRead() {
InternalGZIPOutputStream gzipOut = _gzipOut;
if (gzipOut != null)
@ -333,6 +376,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
else
return 0;
}
public long getTotalCompressed() {
InternalGZIPOutputStream gzipOut = _gzipOut;
if (gzipOut != null)
@ -368,9 +412,9 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
protected static String formatHeaders(Map<String, List<String>> headers, StringBuilder command) {
StringBuilder buf = new StringBuilder(command.length() + headers.size() * 64);
buf.append(command.toString().trim()).append("\r\n");
for (Iterator<String> iter = headers.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
for(String val: headers.get(name)) {
for (Map.Entry<String, List<String>> e : headers.entrySet()) {
String name = e.getKey();
for(String val: e.getValue()) {
buf.append(name.trim()).append(": ").append(val.trim()).append("\r\n");
}
}

View File

@ -10,7 +10,13 @@ import java.util.List;
import java.util.StringTokenizer;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.Base32;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.irc.DCCClientManager;
import net.i2p.i2ptunnel.irc.DCCHelper;
import net.i2p.i2ptunnel.irc.I2PTunnelDCCServer;
import net.i2p.i2ptunnel.irc.IrcInboundFilter;
import net.i2p.i2ptunnel.irc.IrcOutboundFilter;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
@ -18,7 +24,7 @@ import net.i2p.util.Log;
/**
* Todo: Can we extend I2PTunnelClient instead and remove some duplicated code?
*/
public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable {
public class I2PTunnelIRCClient extends I2PTunnelClientBase {
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
@ -27,6 +33,14 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
protected List<Destination> dests;
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000; // -1
protected long readTimeout = DEFAULT_READ_TIMEOUT;
private final boolean _dccEnabled;
private I2PTunnelDCCServer _DCCServer;
private DCCClientManager _DCCClientManager;
/**
* @since 0.8.9
*/
public static final String PROP_DCC = "i2ptunnel.ircclient.enableDCC";
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
@ -75,23 +89,28 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
setName("IRC Client on " + tunnel.listenHost + ':' + localPort);
_dccEnabled = Boolean.valueOf(tunnel.getClientOptions().getProperty(PROP_DCC)).booleanValue();
// TODO add some prudent tunnel options (or is it too late?)
startRunning();
notifyEvent("openIRCClientResult", "ok");
}
protected void clientConnectionRun(Socket s) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("got a connection.");
if (_log.shouldLog(Log.INFO))
_log.info("New connection local addr is: " + s.getLocalAddress() +
" from: " + s.getInetAddress());
Destination clientDest = pickDestination();
I2PSocket i2ps = null;
try {
i2ps = createI2PSocket(clientDest);
i2ps.setReadTimeout(readTimeout);
StringBuffer expectedPong = new StringBuffer();
Thread in = new I2PAppThread(new IrcInboundFilter(s,i2ps, expectedPong, _log), "IRC Client " + __clientId + " in", true);
DCCHelper dcc = _dccEnabled ? new DCC(s.getLocalAddress().getAddress()) : null;
Thread in = new I2PAppThread(new IrcInboundFilter(s,i2ps, expectedPong, _log, dcc), "IRC Client " + __clientId + " in", true);
in.start();
Thread out = new I2PAppThread(new IrcOutboundFilter(s,i2ps, expectedPong, _log), "IRC Client " + __clientId + " out", true);
Thread out = new I2PAppThread(new IrcOutboundFilter(s,i2ps, expectedPong, _log, dcc), "IRC Client " + __clientId + " out", true);
out.start();
} catch (Exception ex) {
if (_log.shouldLog(Log.ERROR))
@ -120,387 +139,112 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
return dests.get(index);
}
/*************************************************************************
*
*/
public static class IrcInboundFilter implements Runnable {
private Socket local;
private I2PSocket remote;
private StringBuffer expectedPong;
private final Log _log;
public IrcInboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong, Log log) {
local=_local;
remote=_remote;
expectedPong=pong;
_log = log;
}
public void run() {
// Todo: Don't use BufferedReader - IRC spec limits line length to 512 but...
BufferedReader in;
OutputStream output;
try {
in = new BufferedReader(new InputStreamReader(remote.getInputStream(), "ISO-8859-1"));
output=local.getOutputStream();
} catch (IOException e) {
if (_log.shouldLog(Log.ERROR))
_log.error("IrcInboundFilter: no streams",e);
return;
@Override
public boolean close(boolean forced) {
synchronized(this) {
if (_DCCServer != null) {
_DCCServer.close(forced);
_DCCServer = null;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("IrcInboundFilter: Running.");
try {
while(true)
{
try {
String inmsg = in.readLine();
if(inmsg==null)
break;
if(inmsg.endsWith("\r"))
inmsg=inmsg.substring(0,inmsg.length()-1);
if (_log.shouldLog(Log.DEBUG))
_log.debug("in: [" + inmsg + "]");
String outmsg = inboundFilter(inmsg, expectedPong);
if(outmsg!=null)
{
if(!inmsg.equals(outmsg)) {
if (_log.shouldLog(Log.WARN)) {
_log.warn("inbound FILTERED: "+outmsg);
_log.warn(" - inbound was: "+inmsg);
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info("inbound: "+outmsg);
}
outmsg=outmsg+"\r\n"; // rfc1459 sec. 2.3
output.write(outmsg.getBytes("ISO-8859-1"));
// probably doesn't do much but can't hurt
output.flush();
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("inbound BLOCKED: "+inmsg);
}
} catch (IOException e1) {
if (_log.shouldLog(Log.WARN))
_log.warn("IrcInboundFilter: disconnected",e1);
break;
}
}
} catch (RuntimeException re) {
_log.error("Error filtering inbound data", re);
} finally {
if (local != null) try { local.close(); } catch (IOException e) {}
}
if(_log.shouldLog(Log.DEBUG))
_log.debug("IrcInboundFilter: Done.");
}
}
/*************************************************************************
*
*/
public static class IrcOutboundFilter implements Runnable {
private Socket local;
private I2PSocket remote;
private StringBuffer expectedPong;
private final Log _log;
public IrcOutboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong, Log log) {
local=_local;
remote=_remote;
expectedPong=pong;
_log = log;
}
public void run() {
// Todo: Don't use BufferedReader - IRC spec limits line length to 512 but...
BufferedReader in;
OutputStream output;
try {
in = new BufferedReader(new InputStreamReader(local.getInputStream(), "ISO-8859-1"));
output=remote.getOutputStream();
} catch (IOException e) {
if (_log.shouldLog(Log.ERROR))
_log.error("IrcOutboundFilter: no streams",e);
return;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("IrcOutboundFilter: Running.");
try {
while(true)
{
try {
String inmsg = in.readLine();
if(inmsg==null)
break;
if(inmsg.endsWith("\r"))
inmsg=inmsg.substring(0,inmsg.length()-1);
if (_log.shouldLog(Log.DEBUG))
_log.debug("out: [" + inmsg + "]");
String outmsg = outboundFilter(inmsg, expectedPong);
if(outmsg!=null)
{
if(!inmsg.equals(outmsg)) {
if (_log.shouldLog(Log.WARN)) {
_log.warn("outbound FILTERED: "+outmsg);
_log.warn(" - outbound was: "+inmsg);
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info("outbound: "+outmsg);
}
outmsg=outmsg+"\r\n"; // rfc1459 sec. 2.3
output.write(outmsg.getBytes("ISO-8859-1"));
// save 250 ms in streaming
output.flush();
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("outbound BLOCKED: "+"\""+inmsg+"\"");
}
} catch (IOException e1) {
if (_log.shouldLog(Log.WARN))
_log.warn("IrcOutboundFilter: disconnected",e1);
break;
}
}
} catch (RuntimeException re) {
_log.error("Error filtering outbound data", re);
} finally {
if (remote != null) try { remote.close(); } catch (IOException e) {}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("IrcOutboundFilter: Done.");
if (_DCCClientManager != null) {
_DCCClientManager.close(forced);
_DCCClientManager = null;
}
}
/*************************************************************************
*
*/
public static String inboundFilter(String s, StringBuffer expectedPong) {
String field[]=s.split(" ",4);
String command;
int idx=0;
final String[] allowedCommands =
{
// "NOTICE", // can contain CTCP
//"PING",
//"PONG",
"MODE",
"JOIN",
"NICK",
"QUIT",
"PART",
"WALLOPS",
"ERROR",
"KICK",
"H", // "hide operator status" (after kicking an op)
"TOPIC"
};
if(field[0].charAt(0)==':')
idx++;
try { command = field[idx++]; }
catch (IndexOutOfBoundsException ioobe) // wtf, server sent borked command?
{
//_log.warn("Dropping defective message: index out of bounds while extracting command.");
return null;
}
idx++; //skip victim
// Allow numerical responses
try {
new Integer(command);
return s;
} catch(NumberFormatException nfe){}
if ("PING".equalsIgnoreCase(command))
return "PING 127.0.0.1"; // no way to know what the ircd to i2ptunnel server con is, so localhost works
if ("PONG".equalsIgnoreCase(command)) {
// Turn the received ":irc.freshcoffee.i2p PONG irc.freshcoffee.i2p :127.0.0.1"
// into ":127.0.0.1 PONG 127.0.0.1 " so that the caller can append the client's extra parameter
// though, does 127.0.0.1 work for irc clients connecting remotely? and for all of them? sure would
// be great if irc clients actually followed the RFCs here, but i guess thats too much to ask.
// If we haven't PINGed them, or the PING we sent isn't something we know how to filter, this
// is blank.
//
// String pong = expectedPong.length() > 0 ? expectedPong.toString() : null;
// If we aren't going to rewrite it, pass it through
String pong = expectedPong.length() > 0 ? expectedPong.toString() : s;
expectedPong.setLength(0);
return pong;
}
// Allow all allowedCommands
for(int i=0;i<allowedCommands.length;i++) {
if(allowedCommands[i].equalsIgnoreCase(command))
return s;
}
// Allow PRIVMSG, but block CTCP.
if("PRIVMSG".equalsIgnoreCase(command) || "NOTICE".equalsIgnoreCase(command))
{
String msg;
msg = field[idx++];
if(msg.indexOf(0x01) >= 0) // CTCP marker ^A can be anywhere, not just immediately after the ':'
{
// CTCP
msg=msg.substring(2);
if(msg.startsWith("ACTION ")) {
// /me says hello
return s;
}
return null; // Block all other ctcp
}
return s;
}
// Block the rest
return null;
return super.close(forced);
}
public static String outboundFilter(String s, StringBuffer expectedPong) {
String field[]=s.split(" ",3);
String command;
final String[] allowedCommands =
{
// "NOTICE", // can contain CTCP
"MODE",
"JOIN",
"NICK",
"WHO",
"WHOIS",
"LIST",
"NAMES",
"NICK",
// "QUIT", // replace with a filtered QUIT to hide client quit messages
"SILENCE",
"MAP", // seems safe enough, the ircd should protect themselves though
// "PART", // replace with filtered PART to hide client part messages
"OPER",
// "PONG", // replaced with a filtered PING/PONG since some clients send the server IP (thanks aardvax!)
// "PING",
"KICK",
"HELPME",
"RULES",
"TOPIC",
"ISON" // jIRCii uses this for a ping (response is 303)
};
if(field[0].length()==0)
return null; // W T F?
if(field[0].charAt(0)==':')
return null; // wtf
command = field[0].toUpperCase();
//
// Start of the DCCHelper interface
//
if ("PING".equals(command)) {
// Most clients just send a PING and are happy with any old PONG. Others,
// like BitchX, actually expect certain behavior. It sends two different pings:
// "PING :irc.freshcoffee.i2p" and "PING 1234567890 127.0.0.1" (where the IP is the proxy)
// the PONG to the former seems to be "PONG 127.0.0.1", while the PONG to the later is
// ":irc.freshcoffee.i2p PONG irc.freshcoffe.i2p :1234567890".
// We don't want to send them our proxy's IP address, so we need to rewrite the PING
// sent to the server, but when we get a PONG back, use what we expected, rather than
// what they sent.
//
// Yuck.
private class DCC implements DCCHelper {
String rv = null;
expectedPong.setLength(0);
if (field.length == 1) { // PING
rv = "PING";
// If we aren't rewriting the PING don't rewrite the PONG
// expectedPong.append("PONG 127.0.0.1");
} else if (field.length == 2) { // PING nonce
rv = "PING " + field[1];
// If we aren't rewriting the PING don't rewrite the PONG
// expectedPong.append("PONG ").append(field[1]);
} else if (field.length == 3) { // PING nonce serverLocation
rv = "PING " + field[1];
expectedPong.append("PONG ").append(field[2]).append(" :").append(field[1]); // PONG serverLocation nonce
} else {
//if (_log.shouldLog(Log.ERROR))
// _log.error("IRC client sent a PING we don't understand, filtering it (\"" + s + "\")");
rv = null;
}
//if (_log.shouldLog(Log.WARN))
// _log.warn("sending ping [" + rv + "], waiting for [" + expectedPong + "] orig was [" + s + "]");
return rv;
}
if ("PONG".equals(command))
return "PONG 127.0.0.1"; // no way to know what the ircd to i2ptunnel server con is, so localhost works
private final byte[] _localAddr;
// Allow all allowedCommands
for(int i=0;i<allowedCommands.length;i++)
{
if(allowedCommands[i].equals(command))
return s;
}
// mIRC sends "NOTICE user :DCC Send file (IP)"
// in addition to the CTCP version
if("NOTICE".equals(command))
{
String msg = field[2];
if(msg.startsWith(":DCC "))
return null;
// fall through
}
// Allow PRIVMSG, but block CTCP (except ACTION).
if("PRIVMSG".equals(command) || "NOTICE".equals(command))
{
String msg;
msg = field[2];
if(msg.indexOf(0x01) >= 0) // CTCP marker ^A can be anywhere, not just immediately after the ':'
{
// CTCP
msg=msg.substring(2);
if(msg.startsWith("ACTION ")) {
// /me says hello
return s;
}
return null; // Block all other ctcp
}
return s;
}
if("USER".equals(command)) {
int idx = field[2].lastIndexOf(":");
if(idx<0)
return "USER user hostname localhost :realname";
String realname = field[2].substring(idx+1);
String ret = "USER "+field[1]+" hostname localhost :"+realname;
return ret;
}
if ("PART".equals(command)) {
// hide client message
return "PART " + field[1] + " :leaving";
}
if ("QUIT".equals(command)) {
return "QUIT :leaving";
}
// Block the rest
return null;
/**
* @param local Our IP address, from the IRC client's perspective
*/
public DCC(byte[] local) {
if (local.length == 4)
_localAddr = local;
else
_localAddr = new byte[] {127, 0, 0, 1};
}
public boolean isEnabled() {
return _dccEnabled;
}
public String getB32Hostname() {
return Base32.encode(sockMgr.getSession().getMyDestination().calculateHash().getData()) + ".b32.i2p";
}
public byte[] getLocalAddress() {
return _localAddr;
}
public int newOutgoing(byte[] ip, int port, String type) {
I2PTunnelDCCServer server;
synchronized(this) {
if (_DCCServer == null) {
if (_log.shouldLog(Log.INFO))
_log.info("Starting DCC Server");
_DCCServer = new I2PTunnelDCCServer(sockMgr, l, I2PTunnelIRCClient.this, getTunnel());
// TODO add some prudent tunnel options (or is it too late?)
_DCCServer.startRunning();
}
server = _DCCServer;
}
int rv = server.newOutgoing(ip, port, type);
if (_log.shouldLog(Log.INFO))
_log.info("New outgoing " + type + ' ' + port + " returns " + rv);
return rv;
}
public int newIncoming(String b32, int port, String type) {
DCCClientManager tracker;
synchronized(this) {
if (_DCCClientManager == null) {
if (_log.shouldLog(Log.INFO))
_log.info("Starting DCC Client");
_DCCClientManager = new DCCClientManager(sockMgr, l, I2PTunnelIRCClient.this, getTunnel());
}
tracker = _DCCClientManager;
}
// The tracker starts our client
int rv = tracker.newIncoming(b32, port, type);
if (_log.shouldLog(Log.INFO))
_log.info("New incoming " + type + ' ' + b32 + ' ' + port + " returns " + rv);
return rv;
}
public int resumeOutgoing(int port) {
DCCClientManager tracker = _DCCClientManager;
if (tracker != null)
return tracker.resumeOutgoing(port);
return -1;
}
public int resumeIncoming(int port) {
I2PTunnelDCCServer server = _DCCServer;
if (server != null)
return server.resumeIncoming(port);
return -1;
}
public int acceptOutgoing(int port) {
I2PTunnelDCCServer server = _DCCServer;
if (server != null)
return server.acceptOutgoing(port);
return -1;
}
public int acceptIncoming(int port) {
DCCClientManager tracker = _DCCClientManager;
if (tracker != null)
return tracker.acceptIncoming(port);
return -1;
}
}
}

View File

@ -63,6 +63,13 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
public static final String PROP_HOSTNAME_DEFAULT="%f.b32.i2p";
private static final long HEADER_TIMEOUT = 60*1000;
private final static byte[] ERR_UNAVAILABLE =
(":ircserver.i2p 499 you :" +
"This I2P IRC server is unvailable. It may be down or undergoing maintenance. " +
"Please try again later." +
"\r\n")
.getBytes();
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router
@ -125,7 +132,11 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
Socket s = new Socket(remoteHost, remotePort);
new I2PTunnelRunner(s, socket, slock, null, modifiedRegistration.getBytes(), null);
} catch (SocketException ex) {
// TODO send the equivalent of a 503?
try {
// Send a response so the user doesn't just see a disconnect
// and blame his router or the network.
socket.getOutputStream().write(ERR_UNAVAILABLE);
} catch (IOException ioe) {}
try {
socket.close();
} catch (IOException ioe) {}

View File

@ -12,6 +12,7 @@ import java.net.SocketException;
import java.util.HashMap;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.ByteArray;
import net.i2p.util.ByteCache;
@ -20,10 +21,10 @@ import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErrorListener {
private final static Log _log = new Log(I2PTunnelRunner.class);
protected final Log _log;
private static volatile long __runnerId;
private long _runnerId;
private final long _runnerId;
/**
* max bytes streamed in a packet - smaller ones might be filled
* up to this size. Larger ones are not split (at least not on
@ -34,35 +35,52 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
static final int NETWORK_BUFFER_SIZE = MAX_PACKET_SIZE;
private Socket s;
private I2PSocket i2ps;
final Object slock, finishLock = new Object();
private final Socket s;
private final I2PSocket i2ps;
private final Object slock, finishLock = new Object();
boolean finished = false;
HashMap ostreams, sockets;
byte[] initialI2PData;
byte[] initialSocketData;
private final byte[] initialI2PData;
private final byte[] initialSocketData;
/** when the last data was sent/received (or -1 if never) */
private long lastActivityOn;
/** when the runner started up */
private long startedOn;
private List sockList;
private final long startedOn;
private final List<I2PSocket> sockList;
/** if we die before receiving any data, run this job */
private Runnable onTimeout;
private final Runnable onTimeout;
private long totalSent;
private long totalReceived;
private volatile long __forwarderId;
public I2PTunnelRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData, List sockList) {
public I2PTunnelRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData,
List<I2PSocket> sockList) {
this(s, i2ps, slock, initialI2PData, null, sockList, null);
}
public I2PTunnelRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData, byte[] initialSocketData, List sockList) {
public I2PTunnelRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData,
byte[] initialSocketData, List<I2PSocket> sockList) {
this(s, i2ps, slock, initialI2PData, initialSocketData, sockList, null);
}
public I2PTunnelRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData, List sockList, Runnable onTimeout) {
public I2PTunnelRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData,
List<I2PSocket> sockList, Runnable onTimeout) {
this(s, i2ps, slock, initialI2PData, null, sockList, onTimeout);
}
public I2PTunnelRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData, byte[] initialSocketData, List sockList, Runnable onTimeout) {
/**
* Starts itself
*
* @param slock the socket lock, non-null
* @param initialI2PData may be null
* @param initialSocketData may be null
* @param sockList may be null. Caller must add i2ps to the list! It will be removed here on completion.
* Will synchronize on slock when removing.
* @param onTimeout May be null. If non-null and no data (except initial data) was sent or received,
it will be run before closing s.
*/
public I2PTunnelRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData,
byte[] initialSocketData, List<I2PSocket> sockList, Runnable onTimeout) {
this.sockList = sockList;
this.s = s;
this.i2ps = i2ps;
@ -72,6 +90,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
this.onTimeout = onTimeout;
lastActivityOn = -1;
startedOn = Clock.getInstance().now();
_log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
if (_log.shouldLog(Log.INFO))
_log.info("I2PTunnelRunner started");
_runnerId = ++__runnerId;
@ -84,6 +103,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
* have we closed at least one (if not both) of the streams
* [aka we're done running the streams]?
*
* @deprecated unused
*/
public boolean isFinished() {
return finished;
@ -93,7 +113,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
* When was the last data for this runner sent or received?
*
* @return date (ms since the epoch), or -1 if no data has been transferred yet
*
* @deprecated unused
*/
public long getLastActivityOn() {
return lastActivityOn;
@ -123,6 +143,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
InputStream i2pin = i2ps.getInputStream();
OutputStream i2pout = i2ps.getOutputStream(); //new BufferedOutputStream(i2ps.getOutputStream(), MAX_PACKET_SIZE);
if (initialI2PData != null) {
// why synchronize this? we could be in here a LONG time for large initial data
synchronized (slock) {
// this does not increment totalSent
i2pout.write(initialI2PData);
@ -162,8 +183,11 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
if (_log.shouldLog(Log.DEBUG))
_log.debug("runner has a timeout job, totalReceived = " + totalReceived
+ " totalSent = " + totalSent + " job = " + onTimeout);
// should we only look at totalReceived?
if ( (totalSent <= 0) && (totalReceived <= 0) )
// Run even if totalSent > 0, as that's probably POST data.
// This will be run even if initialSocketData != null, it's the timeout job's
// responsibility to know that and decide whether or not to write to the socket.
// HTTPClient never sets initialSocketData.
if (totalReceived <= 0)
onTimeout.run();
}
@ -175,6 +199,20 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
} catch (IOException ex) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Error forwarding", ex);
} catch (IllegalStateException ise) {
// JamVM (Gentoo: jamvm-1.5.4, gnu-classpath-0.98+gmp)
//java.nio.channels.NotYetConnectedException
// at gnu.java.nio.SocketChannelImpl.write(SocketChannelImpl.java:240)
// at gnu.java.net.PlainSocketImpl$SocketOutputStream.write(PlainSocketImpl.java:668)
// at java.io.OutputStream.write(OutputStream.java:86)
// at net.i2p.i2ptunnel.I2PTunnelHTTPClient.writeFooter(I2PTunnelHTTPClient.java:1029)
// at net.i2p.i2ptunnel.I2PTunnelHTTPClient.writeErrorMessage(I2PTunnelHTTPClient.java:1114)
// at net.i2p.i2ptunnel.I2PTunnelHTTPClient.handleHTTPClientException(I2PTunnelHTTPClient.java:1131)
// at net.i2p.i2ptunnel.I2PTunnelHTTPClient.access$000(I2PTunnelHTTPClient.java:67)
// at net.i2p.i2ptunnel.I2PTunnelHTTPClient$OnTimeout.run(I2PTunnelHTTPClient.java:1052)
// at net.i2p.i2ptunnel.I2PTunnelRunner.run(I2PTunnelRunner.java:167)
if (_log.shouldLog(Log.WARN))
_log.warn("gnu?", ise);
} catch (Exception e) {
if (_log.shouldLog(Log.ERROR))
_log.error("Internal error", e);
@ -184,22 +222,23 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
if (s != null)
s.close();
} catch (IOException ex) {
if (_log.shouldLog(Log.ERROR))
_log.error("Could not close java socket", ex);
if (_log.shouldLog(Log.WARN))
_log.warn("Could not close java socket", ex);
}
if (i2ps != null) {
try {
i2ps.close();
} catch (IOException ex) {
if (_log.shouldLog(Log.ERROR))
_log.error("Could not close I2PSocket", ex);
if (_log.shouldLog(Log.WARN))
_log.warn("Could not close I2PSocket", ex);
}
i2ps.setSocketErrorListener(null);
}
}
}
protected void close(OutputStream out, InputStream in, OutputStream i2pout, InputStream i2pin, Socket s, I2PSocket i2ps, Thread t1, Thread t2) throws InterruptedException, IOException {
protected void close(OutputStream out, InputStream in, OutputStream i2pout, InputStream i2pin,
Socket s, I2PSocket i2ps, Thread t1, Thread t2) throws InterruptedException {
try {
out.flush();
} catch (IOException ioe) {
@ -210,12 +249,28 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
} catch (IOException ioe) {
// ignore
}
in.close();
i2pin.close();
try {
in.close();
} catch (IOException ioe) {
// ignore
}
try {
i2pin.close();
} catch (IOException ioe) {
// ignore
}
// ok, yeah, there's a race here in theory, if data comes in after flushing and before
// closing, but its better than before...
s.close();
i2ps.close();
try {
s.close();
} catch (IOException ioe) {
// ignore
}
try {
i2ps.close();
} catch (IOException ioe) {
// ignore
}
t1.join(30*1000);
t2.join(30*1000);
}
@ -237,11 +292,11 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
private class StreamForwarder extends I2PAppThread {
InputStream in;
OutputStream out;
String direction;
private boolean _toI2P;
private ByteCache _cache;
private final InputStream in;
private final OutputStream out;
private final String direction;
private final boolean _toI2P;
private final ByteCache _cache;
private StreamForwarder(InputStream in, OutputStream out, boolean toI2P) {
this.in = in;
@ -330,7 +385,17 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr
_log.warn(direction + ": Error closing input stream", ex);
}
try {
out.flush();
// Thread must close() before exiting for a PipedOutputStream,
// or else input end gives up and we have data loss.
// http://techtavern.wordpress.com/2008/07/16/whats-this-ioexception-write-end-dead/
//out.flush();
// DON'T close if we have a timeout job and we haven't received anything,
// or else the timeout job can't write the error message to the stream.
// close() above will close it after the timeout job is run.
if (!(onTimeout != null && (!_toI2P) && totalReceived <= 0))
out.close();
else if (_log.shouldLog(Log.INFO))
_log.info(direction + ": not closing so we can write the error message");
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn(direction + ": Error flushing to close", ioe);

View File

@ -47,7 +47,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
protected int remotePort;
private boolean _usePool;
private Logging l;
protected Logging l;
private static final long DEFAULT_READ_TIMEOUT = -1; // 3*60*1000;
/** default timeout to 3 minutes - override if desired */
@ -67,11 +67,15 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
protected I2PTunnelTask task = null;
protected boolean bidir = false;
private ThreadPoolExecutor _executor;
/** unused? port should always be specified */
private int DEFAULT_LOCALPORT = 4488;
protected int localPort = DEFAULT_LOCALPORT;
/**
* @param privData Base64-encoded private key data,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
@ -83,6 +87,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
/**
* @param privkey file containing the private key data,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
* @param privkeyname the name of the privKey file, not clear why we need this too
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
@ -104,6 +111,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
/**
* @param privData stream containing the private key data,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
* @param privkeyname the name of the privKey file, not clear why we need this too
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
@ -113,10 +123,28 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
init(host, port, privData, privkeyname, l);
}
/**
* @param sktMgr the existing socket manager
* @since 0.8.9
*/
public I2PTunnelServer(InetAddress host, int port, I2PSocketManager sktMgr,
Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super("Server at " + host + ':' + port, notifyThis, tunnel);
this.l = l;
this.remoteHost = host;
this.remotePort = port;
_log = tunnel.getContext().logManager().getLog(getClass());
sockMgr = sktMgr;
open = true;
}
private static final int RETRY_DELAY = 20*1000;
private static final int MAX_RETRIES = 4;
/**
* @param privData stream containing the private key data,
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
* @param privkeyname the name of the privKey file, not clear why we need this too
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
@ -259,6 +287,10 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
//l.log("Server shut down.");
open = false;
if (_usePool && _executor != null) {
_executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
_executor.shutdownNow();
}
return true;
}
}
@ -283,7 +315,6 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
*/
public void run() {
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
ThreadPoolExecutor executor = null;
if (_log.shouldLog(Log.WARN)) {
if (_usePool)
_log.warn("Starting executor with " + getHandlerCount() + " threads max");
@ -291,7 +322,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
_log.warn("Threads disabled, running blockingHandles inline");
}
if (_usePool) {
executor = new CustomThreadPoolExecutor(getHandlerCount(), "ServerHandler pool " + remoteHost + ':' + remotePort);
_executor = new CustomThreadPoolExecutor(getHandlerCount(), "ServerHandler pool " + remoteHost + ':' + remotePort);
}
while (open) {
try {
@ -299,7 +330,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
if (i2ps == null) throw new I2PException("I2PServerSocket closed");
if (_usePool) {
try {
executor.execute(new Handler(i2ps));
_executor.execute(new Handler(i2ps));
} catch (RejectedExecutionException ree) {
try {
i2ps.close();
@ -328,8 +359,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
// ignored, we never set the timeout
}
}
if (executor != null)
executor.shutdownNow();
if (_executor != null)
_executor.shutdownNow();
}
/**

View File

@ -13,9 +13,7 @@ import net.i2p.util.EventDispatcherImpl;
* Either a Server or a Client.
*/
public abstract class I2PTunnelTask implements EventDispatcher {
private final EventDispatcherImpl _event = new EventDispatcherImpl();
public abstract class I2PTunnelTask extends EventDispatcherImpl {
private int id;
private String name;
@ -77,41 +75,4 @@ public abstract class I2PTunnelTask implements EventDispatcher {
public String toString() {
return name;
}
/* Required by the EventDispatcher interface */
public EventDispatcher getEventDispatcher() {
return _event;
}
public void attachEventDispatcher(EventDispatcher e) {
_event.attachEventDispatcher(e.getEventDispatcher());
}
public void detachEventDispatcher(EventDispatcher e) {
_event.detachEventDispatcher(e.getEventDispatcher());
}
public void notifyEvent(String e, Object a) {
_event.notifyEvent(e, a);
}
public Object getEventValue(String n) {
return _event.getEventValue(n);
}
public Set getEvents() {
return _event.getEvents();
}
public void ignoreEvents() {
_event.ignoreEvents();
}
public void unIgnoreEvents() {
_event.unIgnoreEvents();
}
public Object waitEventValue(String n) {
return _event.waitEventValue(n);
}
}
}

View File

@ -15,11 +15,10 @@ import net.i2p.util.Log;
* @since 0.7.9
*/
class InternalSocketRunner implements Runnable {
private I2PTunnelClientBase client;
private int port;
private final I2PTunnelClientBase client;
private final int port;
private ServerSocket ss;
private boolean open;
private static final Log _log = new Log(InternalSocketRunner.class);
private volatile boolean open;
/** starts the runner */
InternalSocketRunner(I2PTunnelClientBase client) {
@ -33,13 +32,14 @@ class InternalSocketRunner implements Runnable {
try {
this.ss = new InternalServerSocket(this.port);
this.open = true;
while (true) {
while (this.open) {
Socket s = this.ss.accept();
this.client.manageConnection(s);
}
} catch (IOException ex) {
if (this.open) {
_log.error("Error listening for internal connections on port " + this.port, ex);
Log log = new Log(InternalSocketRunner.class);
log.error("Error listening for internal connections on port " + this.port, ex);
}
this.open = false;
}
@ -47,10 +47,10 @@ class InternalSocketRunner implements Runnable {
void stopRunning() {
if (this.open) {
this.open = false;
try {
this.ss.close();
} catch (IOException ex) {}
this.open = false;
}
}
}

View File

@ -22,16 +22,19 @@ import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream;
/**
* Coordinate the runtime operation and configuration of a tunnel.
* Coordinate the runtime operation and configuration of a single I2PTunnel.
* An I2PTunnel tracks one or more I2PTunnelTasks and one or more I2PSessions.
* Usually one of each.
*
* These objects are bundled together under a TunnelControllerGroup where the
* entire group is stored / loaded from a single config file.
*
*/
public class TunnelController implements Logging {
private Log _log;
private final Log _log;
private Properties _config;
private I2PTunnel _tunnel;
private List<String> _messages;
private final I2PTunnel _tunnel;
private final List<String> _messages;
private List<I2PSession> _sessions;
private boolean _running;
private boolean _starting;
@ -153,6 +156,15 @@ public class TunnelController implements Logging {
_log.warn("Cannot start the tunnel - no type specified");
return;
}
// Config options may have changed since instantiation, so do this again.
// Or should we take it out of the constructor completely?
if (type.endsWith("server") || getPersistentClientKey()) {
boolean ok = createPrivateKey();
if (!ok) {
log("Failed to start tunnel " + getName() + " as the private key file could not be created");
return;
}
}
setI2CPOptions();
setSessionOptions();
if ("httpclient".equals(type)) {

View File

@ -26,7 +26,7 @@ import net.i2p.util.OrderedProperties;
* Warning - this is a singleton. Todo: fix
*/
public class TunnelControllerGroup {
private final Log _log;
private Log _log;
private static TunnelControllerGroup _instance;
static final String DEFAULT_CONFIG_FILE = "i2ptunnel.config";
@ -55,6 +55,7 @@ public class TunnelControllerGroup {
_configFile = configFile;
_sessions = new HashMap(4);
loadControllers(_configFile);
I2PAppContext.getGlobalContext().addShutdownTask(new Shutdown());
}
public static void main(String args[]) {
@ -71,6 +72,34 @@ public class TunnelControllerGroup {
}
}
}
/**
* Warning - destroys the singleton!
* @since 0.8.8
*/
private static class Shutdown implements Runnable {
public void run() {
shutdown();
}
}
/**
* Warning - destroys the singleton!
* Caller must root a new context before calling instance() or main() again.
* Agressively kill and null everything to reduce memory usage in the JVM
* after stopping, and to recognize what must be reinitialized on restart (Android)
*
* @since 0.8.8
*/
public static void shutdown() {
synchronized (TunnelControllerGroup.class) {
if (_instance == null) return;
_instance.unloadControllers();
_instance._log = null;
_instance = null;
}
I2PTunnelClientBase.killClientExecutor();
}
/**
* Load up all of the tunnels configured in the given file (but do not start

View File

@ -0,0 +1,236 @@
package net.i2p.i2ptunnel.irc;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Base32;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.Logging;
import net.i2p.util.EventDispatcher;
import net.i2p.util.Log;
/**
* Start, track, and expire the I2PTunnelDCCClients.
*
* <pre>
*
* direct conn
* <---> I2PTunnelDCCServer <--------------->I2PTunnelDCCClient <---->
* originating responding
* chat client chat client
* CHAT ---> I2PTunnelIRCClient --> IRC server --> I2TunnelIRCClient ----->
* SEND ---> I2PTunnelIRCClient --> IRC server --> I2TunnelIRCClient ----->
* RESUME <--- I2PTunnelIRCClient <-- IRC server <-- I2TunnelIRCClient <-----
* ACCEPT ---> I2PTunnelIRCClient --> IRC server --> I2TunnelIRCClient ----->
*
* </pre>
*
* @since 0.8.9
*/
public class DCCClientManager extends EventReceiver {
private final I2PSocketManager sockMgr;
private final EventDispatcher _dispatch;
private final Logging l;
private final I2PTunnel _tunnel;
private final Log _log;
/** key is the DCC client's local port */
private final ConcurrentHashMap<Integer, I2PTunnelDCCClient> _incoming;
/** key is the DCC client's local port */
private final ConcurrentHashMap<Integer, I2PTunnelDCCClient> _active;
/** key is the DCC client's local port */
private final ConcurrentHashMap<Integer, I2PTunnelDCCClient> _complete;
// list of client tunnels?
private static long _id;
private static final int MAX_INCOMING_PENDING = 10;
private static final int MAX_INCOMING_ACTIVE = 10;
private static final long ACTIVE_EXPIRE = 60*60*1000;
public DCCClientManager(I2PSocketManager sktMgr, Logging logging,
EventDispatcher dispatch, I2PTunnel tunnel) {
sockMgr = sktMgr;
l = logging;
_dispatch = dispatch;
_tunnel = tunnel;
_log = tunnel.getContext().logManager().getLog(DCCClientManager.class);
_incoming = new ConcurrentHashMap(8);
_active = new ConcurrentHashMap(8);
_complete = new ConcurrentHashMap(8);
}
public boolean close(boolean forced) {
for (I2PTunnelDCCClient c : _incoming.values()) {
c.stop();
}
_incoming.clear();
for (I2PTunnelDCCClient c : _active.values()) {
c.stop();
}
_active.clear();
_complete.clear();
return true;
}
/**
* An incoming DCC request
*
* @param b32 remote dcc server b32 address
* @param port remote dcc server I2P port
* @param type ignored
* @return local DCC client tunnel port or -1 on error
*/
public int newIncoming(String b32, int port, String type) {
return newIncoming(b32, port, type, 0);
}
/**
* @param localPort bind to port or 0; if nonzero it will be the rv
*/
private int newIncoming(String b32, int port, String type, int localPort) {
b32 = b32.toLowerCase();
// do some basic verification before starting the client
if (b32.length() != 60 || !b32.endsWith(".b32.i2p"))
return -1;
byte[] dec = Base32.decode(b32.substring(0, 52));
if (dec == null || dec.length != 32)
return -1;
expireInbound();
if (_incoming.size() >= MAX_INCOMING_PENDING ||
_active.size() >= MAX_INCOMING_PENDING) {
_log.error("Too many incoming DCC, max is " + MAX_INCOMING_PENDING +
'/' + MAX_INCOMING_ACTIVE + " pending/active");
return -1;
}
try {
// Transparent tunnel used for all types...
// Do we need to do any filtering for chat?
I2PTunnelDCCClient cTunnel = new I2PTunnelDCCClient(b32, localPort, port, l, sockMgr,
_dispatch, _tunnel, ++_id);
cTunnel.attachEventDispatcher(this);
int lport = cTunnel.getLocalPort();
if (_log.shouldLog(Log.WARN))
_log.warn("Opened client tunnel at port " + lport +
" pointing to " + b32 + ':' + port);
_incoming.put(Integer.valueOf(lport), cTunnel);
return lport;
} catch (IllegalArgumentException uhe) {
l.log("Could not find listen host to bind to [" + _tunnel.host + "]");
_log.error("Error finding host to bind", uhe);
return -1;
}
}
/**
* An outgoing RESUME request
*
* @param port local DCC client tunnel port
* @return remote DCC server i2p port or -1 on error
*/
public int resumeOutgoing(int port) {
Integer lport = Integer.valueOf(port);
I2PTunnelDCCClient tun = _complete.get(lport);
if (tun == null) {
tun = _active.get(lport);
if (tun == null)
// shouldn't happen
tun = _incoming.get(lport);
}
if (tun != null) {
tun.stop();
return tun.getLocalPort();
}
return -1;
}
/**
* An incoming ACCEPT response
*
* @param port remote dcc server I2P port
* @return local DCC client tunnel port or -1 on error
*/
public int acceptIncoming(int port) {
// do a reverse lookup
for (I2PTunnelDCCClient tun : _complete.values()) {
if (tun.getRemotePort() == port)
return newIncoming(tun.getDest(), port, "ACCEPT", tun.getLocalPort());
}
for (I2PTunnelDCCClient tun : _active.values()) {
if (tun.getRemotePort() == port)
return newIncoming(tun.getDest(), port, "ACCEPT", tun.getLocalPort());
}
for (I2PTunnelDCCClient tun : _incoming.values()) {
if (tun.getRemotePort() == port) {
// shouldn't happen
tun.stop();
return newIncoming(tun.getDest(), port, "ACCEPT", tun.getLocalPort());
}
}
return -1;
}
/**
* The EventReceiver callback
*/
public void notifyEvent(String eventName, Object args) {
if (eventName.equals(I2PTunnelDCCClient.CONNECT_START_EVENT)) {
try {
I2PTunnelDCCClient client = (I2PTunnelDCCClient) args;
connStarted(client);
} catch (ClassCastException cce) {}
} else if (eventName.equals(I2PTunnelDCCClient.CONNECT_STOP_EVENT)) {
try {
Integer port = (Integer) args;
connStopped(port);
} catch (ClassCastException cce) {}
}
}
private void connStarted(I2PTunnelDCCClient client) {
Integer lport = Integer.valueOf(client.getLocalPort());
I2PTunnelDCCClient c = _incoming.remove(lport);
if (c != null) {
_active.put(lport, client);
if (_log.shouldLog(Log.WARN))
_log.warn("Added client tunnel for port " + lport +
" pending count now: " + _incoming.size() +
" active count now: " + _active.size() +
" complete count now: " + _complete.size());
}
}
private void connStopped(Integer lport) {
I2PTunnelDCCClient tun = _incoming.remove(lport);
if (tun != null)
_complete.put(lport, tun);
tun = _active.remove(lport);
if (tun != null)
_complete.put(lport, tun);
if (_log.shouldLog(Log.WARN))
_log.warn("Removed client tunnel for port " + lport +
" pending count now: " + _incoming.size() +
" active count now: " + _active.size() +
" complete count now: " + _complete.size());
}
private void expireInbound() {
for (Iterator<I2PTunnelDCCClient> iter = _incoming.values().iterator(); iter.hasNext(); ) {
I2PTunnelDCCClient c = iter.next();
if (c.getExpires() < _tunnel.getContext().clock().now()) {
iter.remove();
c.stop();
}
}
// shouldn't need to expire active
for (Iterator<I2PTunnelDCCClient> iter = _complete.values().iterator(); iter.hasNext(); ) {
I2PTunnelDCCClient c = iter.next();
if (c.getExpires() < _tunnel.getContext().clock().now()) {
iter.remove();
c.stop();
}
}
}
}

View File

@ -0,0 +1,74 @@
package net.i2p.i2ptunnel.irc;
/**
* Hooks to create and maintain DCC client and server tunnels
*
* @since 0.8.9
*/
public interface DCCHelper {
public boolean isEnabled();
/**
* String to put in the outgoing DCC
*/
public String getB32Hostname();
/**
* Our IP address (taken from the socket), must be IPv4
*/
public byte[] getLocalAddress();
/**
* An outgoing DCC request
*
* @param ip local irc client IP
* @param port local irc client port
* @param type string
* @return local DCC server i2p port or -1 on error
*/
public int newOutgoing(byte[] ip, int port, String type);
/**
* An incoming DCC request
*
* @param b32 remote dcc server b32 address
* @param port remote dcc server I2P port
* @param type string
* @return local DCC client tunnel port or -1 on error
*/
public int newIncoming(String b32, int port, String type);
/**
* An outgoing RESUME request
*
* @param port local DCC client tunnel port
* @return remote DCC server i2p port or -1 on error
*/
public int resumeOutgoing(int port);
/**
* An incoming RESUME request
*
* @param port local dcc server I2P port
* @return local IRC client DCC port or -1 on error
*/
public int resumeIncoming(int port);
/**
* An outgoing ACCEPT response
*
* @param port local irc client DCC port
* @return local DCC server i2p port or -1 on error
*/
public int acceptOutgoing(int port);
/**
* An incoming ACCEPT response
*
* @param port remote dcc server I2P port
* @return local DCC client tunnel port or -1 on error
*/
public int acceptIncoming(int port);
}

View File

@ -0,0 +1,76 @@
package net.i2p.i2ptunnel.irc;
/*
* free (adj.): unencumbered; not under the control of others Written
* by human & jrandom in 2004 and released into the public domain with
* no warranty of any kind, either expressed or implied. It probably
* won't make your computer catch on fire, or eat your children, but
* it might. Use at your own risk.
*
*/
import java.util.Set;
import net.i2p.util.EventDispatcher;
/**
* An implementation of the EventDispatcher interface for
* receiving events via in-line notifyEvent() only.
* Does not support chaining to additional dispatchers.
* Does not support waitEventValue().
* Does not support ignoring.
*
* @since 0.8.9
*/
public abstract class EventReceiver implements EventDispatcher {
public EventDispatcher getEventDispatcher() {
return this;
}
/**
* @throws UnsupportedOperationException always
*/
public void attachEventDispatcher(EventDispatcher ev) {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException always
*/
public void detachEventDispatcher(EventDispatcher ev) {
throw new UnsupportedOperationException();
}
public abstract void notifyEvent(String eventName, Object args);
/**
* @throws UnsupportedOperationException always
*/
public Object getEventValue(String name) {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException always
*/
public Set<String> getEvents() {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException always
*/
public void ignoreEvents() {
throw new UnsupportedOperationException();
}
public void unIgnoreEvents() {}
/**
* @throws UnsupportedOperationException always
*/
public Object waitEventValue(String name) {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,132 @@
/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java)
* (c) 2003 - 2004 mihi
*/
package net.i2p.i2ptunnel.irc;
import java.net.Socket;
import java.io.IOException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelClientBase;
import net.i2p.i2ptunnel.I2PTunnelRunner;
import net.i2p.i2ptunnel.Logging;
import net.i2p.util.EventDispatcher;
import net.i2p.util.Log;
/**
* A standard client, using an existing socket manager.
* Targets a single destination and port.
* Naming resolution is delayed until connect time.
*
* @since 0.8.9
*/
public class I2PTunnelDCCClient extends I2PTunnelClientBase {
// delay resolution until connect time
private final String _dest;
private final int _remotePort;
private long _expires;
private static final long INBOUND_EXPIRE = 30*60*1000;
private static final long INBOUND_STOP_EXPIRE = 30*60*1000;
public static final String CONNECT_START_EVENT = "connectionStarted";
public static final String CONNECT_STOP_EVENT = "connectionStopped";
/**
* @param dest the target, presumably b32
* @param localPort if 0, use any port, get actual port selected with getLocalPort()
* @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router
*/
public I2PTunnelDCCClient(String dest, int localPort, int remotePort, Logging l,
I2PSocketManager sktMgr, EventDispatcher notifyThis,
I2PTunnel tunnel, long clientId) throws IllegalArgumentException {
super(localPort, l, sktMgr, tunnel, notifyThis, clientId);
_dest = dest;
_remotePort = remotePort;
_expires = tunnel.getContext().clock().now() + INBOUND_EXPIRE;
setName("DCC send -> " + dest + ':' + remotePort);
startRunning();
}
/**
* Accept one connection only.
*/
protected void clientConnectionRun(Socket s) {
I2PSocket i2ps = null;
if (_log.shouldLog(Log.INFO))
_log.info("Opening DCC connection to " + _dest + ':' + _remotePort);
Destination dest = _context.namingService().lookup(_dest);
if (dest == null) {
_log.error("Could not find leaseset for DCC connection to " + _dest + ':' + _remotePort);
closeSocket(s);
stop();
notifyEvent(CONNECT_STOP_EVENT, Integer.valueOf(getLocalPort()));
return;
}
I2PSocketOptions opts = sockMgr.buildOptions();
opts.setPort(_remotePort);
try {
i2ps = createI2PSocket(dest, opts);
new Runner(s, i2ps);
} catch (Exception ex) {
_log.error("Could not make DCC connection to " + _dest + ':' + _remotePort, ex);
closeSocket(s);
if (i2ps != null) {
try { i2ps.close(); } catch (IOException ioe) {}
}
notifyEvent(CONNECT_STOP_EVENT, Integer.valueOf(getLocalPort()));
}
stop();
}
public long getExpires() {
return _expires;
}
public String getDest() {
return _dest;
}
public int getRemotePort() {
return _remotePort;
}
/**
* Stop listening for new sockets.
* We can't call super.close() as it kills all sockets in the sockMgr
*/
public void stop() {
open = false;
try {
ss.close();
} catch (IOException ioe) {}
}
/**
* Just so we can do the callbacks
*/
private class Runner extends I2PTunnelRunner {
public Runner(Socket s, I2PSocket i2ps) {
// super calls start()
super(s, i2ps, sockLock, null, mySockets);
}
@Override
public void run() {
_expires = getTunnel().getContext().clock().now() + INBOUND_STOP_EXPIRE;
notifyEvent(CONNECT_START_EVENT, I2PTunnelDCCClient.this);
super.run();
_expires = getTunnel().getContext().clock().now() + INBOUND_STOP_EXPIRE;
notifyEvent(CONNECT_STOP_EVENT, Integer.valueOf(getLocalPort()));
}
}
}

View File

@ -0,0 +1,272 @@
package net.i2p.i2ptunnel.irc;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelRunner;
import net.i2p.i2ptunnel.I2PTunnelServer;
import net.i2p.i2ptunnel.Logging;
import net.i2p.util.EventDispatcher;
import net.i2p.util.Log;
/**
* A standard server that only answers for registered ports,
* and each port can only be used once.
*
* <pre>
*
* direct conn
* <---> I2PTunnelDCCServer <--------------->I2PTunnelDCCClient <---->
* originating responding
* chat client chat client
* CHAT ---> I2PTunnelIRCClient --> IRC server --> I2TunnelIRCClient ----->
* SEND ---> I2PTunnelIRCClient --> IRC server --> I2TunnelIRCClient ----->
* RESUME <--- I2PTunnelIRCClient <-- IRC server <-- I2TunnelIRCClient <-----
* ACCEPT ---> I2PTunnelIRCClient --> IRC server --> I2TunnelIRCClient ----->
*
* </pre>
*
* @since 0.8.9
*/
public class I2PTunnelDCCServer extends I2PTunnelServer {
/** key is the server's local I2P port */
private final ConcurrentHashMap<Integer, LocalAddress> _outgoing;
/** key is the server's local I2P port */
private final ConcurrentHashMap<Integer, LocalAddress> _active;
/** key is the server's local I2P port */
private final ConcurrentHashMap<Integer, LocalAddress> _resume;
private final List<I2PSocket> _sockList;
// list of client tunnels?
private static long _id;
/** just to keep super() happy */
private static final InetAddress DUMMY;
static {
InetAddress dummy = null;
try {
dummy = InetAddress.getByAddress(new byte[4]);
} catch (UnknownHostException uhe) {}
DUMMY = dummy;
}
private static final int MIN_I2P_PORT = 1;
private static final int MAX_I2P_PORT = 65535;
private static final int MAX_OUTGOING_PENDING = 20;
private static final int MAX_OUTGOING_ACTIVE = 20;
private static final long OUTBOUND_EXPIRE = 30*60*1000;
private static final long ACTIVE_EXPIRE = 60*60*1000;
/**
* There's no support for unsolicited incoming I2P connections,
* so there's no server host or port parameters.
*
* @param sktMgr an existing socket manager
* @throws IllegalArgumentException if the I2PTunnel does not contain
* valid config to contact the router
*/
public I2PTunnelDCCServer(I2PSocketManager sktMgr, Logging l,
EventDispatcher notifyThis, I2PTunnel tunnel) {
super(DUMMY, 0, sktMgr, l, notifyThis, tunnel);
_outgoing = new ConcurrentHashMap(8);
_active = new ConcurrentHashMap(8);
_resume = new ConcurrentHashMap(8);
_sockList = new CopyOnWriteArrayList();
}
/**
* An incoming DCC connection, only accept for a known port.
* Passed through without filtering.
*/
@Override
protected void blockingHandle(I2PSocket socket) {
if (_log.shouldLog(Log.INFO))
_log.info("Incoming connection to '" + toString() + "' from: " + socket.getPeerDestination().calculateHash().toBase64());
try {
expireOutbound();
int myPort = socket.getLocalPort();
// Port is a one-time-use only
LocalAddress local = _outgoing.remove(Integer.valueOf(myPort));
if (local == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Rejecting incoming DCC connection for unknown port " + myPort);
try {
socket.close();
} catch (IOException ioe) {}
return;
}
if (_log.shouldLog(Log.WARN))
_log.warn("Incoming DCC connection for I2P port " + myPort +
" sending to " + local.ia + ':' + local.port);
Socket s = new Socket(local.ia, local.port);
_sockList.add(socket);
new I2PTunnelRunner(s, socket, slock, null, _sockList);
local.socket = socket;
local.expire = getTunnel().getContext().clock().now() + OUTBOUND_EXPIRE;
_active.put(Integer.valueOf(myPort), local);
} catch (SocketException ex) {
try {
socket.close();
} catch (IOException ioe) {}
if (_log.shouldLog(Log.ERROR))
_log.error("Error connecting to server " + remoteHost + ':' + remotePort, ex);
} catch (IOException ex) {
_log.error("Error while waiting for I2PConnections", ex);
}
}
@Override
public boolean close(boolean forced) {
_outgoing.clear();
_active.clear();
for (I2PSocket s : _sockList) {
try {
s.close();
} catch (IOException ioe) {}
}
_sockList.clear();
return super.close(forced);
}
/**
* An outgoing DCC request
*
* @param ip local irc client IP
* @param port local irc client port
* @param type ignored
* @return i2p port or -1 on error
*/
public int newOutgoing(byte[] ip, int port, String type) {
return newOutgoing(ip, port, type, 0);
}
/**
* @param port local dcc server I2P port or 0 to pick one at random
*/
private int newOutgoing(byte[] ip, int port, String type, int i2pPort) {
expireOutbound();
if (_outgoing.size() >= MAX_OUTGOING_PENDING ||
_active.size() >= MAX_OUTGOING_ACTIVE) {
_log.error("Too many outgoing DCC, max is " + MAX_OUTGOING_PENDING +
'/' + MAX_OUTGOING_ACTIVE + " pending/active");
return -1;
}
InetAddress ia;
try {
ia = InetAddress.getByAddress(ip);
} catch (UnknownHostException uhe) {
return -1;
}
int limit = i2pPort > 0 ? 10 : 1;
LocalAddress client = new LocalAddress(ia, port, getTunnel().getContext().clock().now() + OUTBOUND_EXPIRE);
for (int i = 0; i < limit; i++) {
int iport;
if (i2pPort > 0)
iport = i2pPort;
else
iport = MIN_I2P_PORT + getTunnel().getContext().random().nextInt(1 + MAX_I2P_PORT - MIN_I2P_PORT);
if (_active.containsKey(Integer.valueOf(iport)))
continue;
LocalAddress old = _outgoing.putIfAbsent(Integer.valueOf(iport), client);
if (old != null)
continue;
// TODO expire in a few minutes
return iport;
}
// couldn't find an unused i2p port
return -1;
}
/**
* An incoming RESUME request
*
* @param port local dcc server I2P port
* @return local IRC client DCC port or -1 on error
*/
public int resumeIncoming(int port) {
Integer iport = Integer.valueOf(port);
LocalAddress local = _active.remove(iport);
if (local != null) {
local.expire = getTunnel().getContext().clock().now() + OUTBOUND_EXPIRE;
_resume.put(Integer.valueOf(local.port), local);
return local.port;
}
local = _outgoing.get(iport);
if (local != null) {
// shouldn't happen
local.expire = getTunnel().getContext().clock().now() + OUTBOUND_EXPIRE;
return local.port;
}
return -1;
}
/**
* An outgoing ACCEPT response
*
* @param port local irc client DCC port
* @return local DCC server i2p port or -1 on error
*/
public int acceptOutgoing(int port) {
// do a reverse lookup
for (Iterator<Map.Entry<Integer, LocalAddress>> iter = _resume.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<Integer, LocalAddress> e = iter.next();
LocalAddress local = e.getValue();
if (local.port == port) {
iter.remove();
return newOutgoing(local.ia.getAddress(), port, "ACCEPT", e.getKey().intValue());
}
}
return -1;
}
private InetAddress getListenHost(Logging l) {
try {
return InetAddress.getByName(getTunnel().listenHost);
} catch (UnknownHostException uhe) {
l.log("Could not find listen host to bind to [" + getTunnel().host + "]");
_log.error("Error finding host to bind", uhe);
notifyEvent("openBaseClientResult", "error");
return null;
}
}
private void expireOutbound() {
for (Iterator<LocalAddress> iter = _outgoing.values().iterator(); iter.hasNext(); ) {
LocalAddress a = iter.next();
if (a.expire < getTunnel().getContext().clock().now())
iter.remove();
}
for (Iterator<LocalAddress> iter = _active.values().iterator(); iter.hasNext(); ) {
LocalAddress a = iter.next();
I2PSocket s = a.socket;
if (s != null && s.isClosed())
iter.remove();
}
}
private static class LocalAddress {
public final InetAddress ia;
public final int port;
public long expire;
public I2PSocket socket;
public LocalAddress(InetAddress a, int p, long exp) {
ia = a;
port = p;
expire = exp;
}
}
}

View File

@ -0,0 +1,507 @@
package net.i2p.i2ptunnel.irc;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
/**
* Static methods to filter individual lines.
* Moved from I2PTunnelIRCClient.java
*
* @since 0.8.9
*/
abstract class IRCFilter {
private static final boolean ALLOW_ALL_DCC_IN = false;
private static final boolean ALLOW_ALL_DCC_OUT = false;
/** does not override DCC handling */
private static final boolean ALLOW_ALL_CTCP_IN = false;
/** does not override DCC handling */
private static final boolean ALLOW_ALL_CTCP_OUT = false;
/*************************************************************************
*
* Modify or filter a single inbound line.
*
* @param helper may be null
* @return the original or modified line, or null if it should be dropped.
*/
public static String inboundFilter(String s, StringBuffer expectedPong, DCCHelper helper) {
String field[]=s.split(" ",4);
String command;
int idx=0;
final String[] allowedCommands =
{
// "NOTICE", // can contain CTCP
//"PING",
//"PONG",
"MODE",
"JOIN",
"NICK",
"QUIT",
"PART",
"WALLOPS",
"ERROR",
"KICK",
"H", // "hide operator status" (after kicking an op)
"TOPIC",
// http://tools.ietf.org/html/draft-mitchell-irc-capabilities-01
"CAP"
};
if(field[0].charAt(0)==':')
idx++;
try { command = field[idx++]; }
catch (IndexOutOfBoundsException ioobe) // wtf, server sent borked command?
{
//_log.warn("Dropping defective message: index out of bounds while extracting command.");
return null;
}
idx++; //skip victim
// Allow numerical responses
try {
new Integer(command);
return s;
} catch(NumberFormatException nfe){}
if ("PING".equalsIgnoreCase(command))
return "PING 127.0.0.1"; // no way to know what the ircd to i2ptunnel server con is, so localhost works
if ("PONG".equalsIgnoreCase(command)) {
// Turn the received ":irc.freshcoffee.i2p PONG irc.freshcoffee.i2p :127.0.0.1"
// into ":127.0.0.1 PONG 127.0.0.1 " so that the caller can append the client's extra parameter
// though, does 127.0.0.1 work for irc clients connecting remotely? and for all of them? sure would
// be great if irc clients actually followed the RFCs here, but i guess thats too much to ask.
// If we haven't PINGed them, or the PING we sent isn't something we know how to filter, this
// is blank.
//
// String pong = expectedPong.length() > 0 ? expectedPong.toString() : null;
// If we aren't going to rewrite it, pass it through
String pong = expectedPong.length() > 0 ? expectedPong.toString() : s;
expectedPong.setLength(0);
return pong;
}
// Allow all allowedCommands
for(int i=0;i<allowedCommands.length;i++) {
if(allowedCommands[i].equalsIgnoreCase(command))
return s;
}
// Allow PRIVMSG, but block CTCP.
if("PRIVMSG".equalsIgnoreCase(command) || "NOTICE".equalsIgnoreCase(command))
{
String msg;
msg = field[idx++];
if(msg.indexOf(0x01) >= 0) // CTCP marker ^A can be anywhere, not just immediately after the ':'
{
// CTCP
// don't even try to parse multiple CTCP in the same message
int count = 0;
for (int i = 0; i < msg.length(); i++) {
if (msg.charAt(i) == 0x01)
count++;
}
if (count != 2)
return null;
msg=msg.substring(2);
if(msg.startsWith("ACTION ")) {
// /me says hello
return s;
}
if (msg.startsWith("DCC ")) {
StringBuilder buf = new StringBuilder(128);
for (int i = 0; i <= idx - 2; i++) {
buf.append(field[i]).append(' ');
}
buf.append(":\001DCC ");
return filterDCCIn(buf.toString(), msg.substring(4), helper);
}
// XDCC looks safe, ip/port happens over regular DCC
// http://en.wikipedia.org/wiki/XDCC
if (msg.toUpperCase().startsWith("XDCC ") && helper != null && helper.isEnabled())
return s;
if (ALLOW_ALL_CTCP_IN)
return s;
return null; // Block all other ctcp
}
return s;
}
// Block the rest
return null;
}
/*************************************************************************
*
* Modify or filter a single outbound line.
*
* @param helper may be null
* @return the original or modified line, or null if it should be dropped.
*/
public static String outboundFilter(String s, StringBuffer expectedPong, DCCHelper helper) {
String field[]=s.split(" ",3);
String command;
final String[] allowedCommands =
{
// "NOTICE", // can contain CTCP
"MODE",
"JOIN",
"NICK",
"WHO",
"WHOIS",
"LIST",
"NAMES",
"NICK",
// "QUIT", // replace with a filtered QUIT to hide client quit messages
"SILENCE",
"MAP", // seems safe enough, the ircd should protect themselves though
// "PART", // replace with filtered PART to hide client part messages
"OPER",
// "PONG", // replaced with a filtered PING/PONG since some clients send the server IP (thanks aardvax!)
// "PING",
"KICK",
"HELPME",
"RULES",
"TOPIC",
"ISON", // jIRCii uses this for a ping (response is 303)
"INVITE",
"AWAY", // should be harmless
// http://tools.ietf.org/html/draft-mitchell-irc-capabilities-01
"CAP"
};
if(field[0].length()==0)
return null; // W T F?
if(field[0].charAt(0)==':')
return null; // wtf
command = field[0].toUpperCase();
if ("PING".equals(command)) {
// Most clients just send a PING and are happy with any old PONG. Others,
// like BitchX, actually expect certain behavior. It sends two different pings:
// "PING :irc.freshcoffee.i2p" and "PING 1234567890 127.0.0.1" (where the IP is the proxy)
// the PONG to the former seems to be "PONG 127.0.0.1", while the PONG to the later is
// ":irc.freshcoffee.i2p PONG irc.freshcoffe.i2p :1234567890".
// We don't want to send them our proxy's IP address, so we need to rewrite the PING
// sent to the server, but when we get a PONG back, use what we expected, rather than
// what they sent.
//
// Yuck.
String rv = null;
expectedPong.setLength(0);
if (field.length == 1) { // PING
rv = "PING";
// If we aren't rewriting the PING don't rewrite the PONG
// expectedPong.append("PONG 127.0.0.1");
} else if (field.length == 2) { // PING nonce
rv = "PING " + field[1];
// If we aren't rewriting the PING don't rewrite the PONG
// expectedPong.append("PONG ").append(field[1]);
} else if (field.length == 3) { // PING nonce serverLocation
rv = "PING " + field[1];
expectedPong.append("PONG ").append(field[2]).append(" :").append(field[1]); // PONG serverLocation nonce
} else {
//if (_log.shouldLog(Log.ERROR))
// _log.error("IRC client sent a PING we don't understand, filtering it (\"" + s + "\")");
rv = null;
}
//if (_log.shouldLog(Log.WARN))
// _log.warn("sending ping [" + rv + "], waiting for [" + expectedPong + "] orig was [" + s + "]");
return rv;
}
if ("PONG".equals(command))
return "PONG 127.0.0.1"; // no way to know what the ircd to i2ptunnel server con is, so localhost works
// Allow all allowedCommands
for(int i=0;i<allowedCommands.length;i++)
{
if(allowedCommands[i].equals(command))
return s;
}
// mIRC sends "NOTICE user :DCC Send file (IP)"
// in addition to the CTCP version
if("NOTICE".equals(command))
{
String msg = field[2];
if(msg.startsWith(":DCC "))
return filterDCCOut(field[0] + ' ' + field[1] + " :DCC ", msg.substring(5), helper);
// fall through
}
// Allow PRIVMSG, but block CTCP (except ACTION).
if("PRIVMSG".equals(command) || "NOTICE".equals(command))
{
String msg;
msg = field[2];
if(msg.indexOf(0x01) >= 0) // CTCP marker ^A can be anywhere, not just immediately after the ':'
{
// CTCP
// don't even try to parse multiple CTCP in the same message
int count = 0;
for (int i = 0; i < msg.length(); i++) {
if (msg.charAt(i) == 0x01)
count++;
}
if (count != 2)
return null;
msg=msg.substring(2);
if(msg.startsWith("ACTION ")) {
// /me says hello
return s;
}
if (msg.startsWith("DCC "))
return filterDCCOut(field[0] + ' ' + field[1] + " :\001DCC ", msg.substring(4), helper);
// XDCC looks safe, ip/port happens over regular DCC
// http://en.wikipedia.org/wiki/XDCC
if (msg.toUpperCase().startsWith("XDCC ") && helper != null && helper.isEnabled())
return s;
if (ALLOW_ALL_CTCP_OUT)
return s;
return null; // Block all other ctcp
}
return s;
}
if("USER".equals(command)) {
int idx = field[2].lastIndexOf(":");
if(idx<0)
return "USER user hostname localhost :realname";
String realname = field[2].substring(idx+1);
String ret = "USER "+field[1]+" hostname localhost :"+realname;
return ret;
}
if ("PART".equals(command)) {
// hide client message
return "PART " + field[1] + " :leaving";
}
if ("QUIT".equals(command)) {
return "QUIT :leaving";
}
// Block the rest
return null;
}
/**
*<pre>
* DCC CHAT chat xxx.b32.i2p i2p-port -> DCC CHAT chat IP port
* DCC SEND file xxx.b32.i2p i2p-port length -> DCC SEND file IP port length
* DCC RESUME file i2p-port offset -> DCC RESUME file port offset
* DCC ACCEPT file i2p-port offset -> DCC ACCEPT file port offset
* DCC xxx -> null
*</pre>
*
* @param pfx the message through the "DCC " part
* @param msg the message after the "DCC " part
* @param helper may be null
* @return the sanitized message or null to block
* @since 0.8.9
*/
private static String filterDCCIn(String pfx, String msg, DCCHelper helper) {
// strip trailing ctcp (other one is in pfx)
int ctcp = msg.indexOf(0x01);
if (ctcp > 0)
msg = msg.substring(0, ctcp);
String[] args = msg.split(" ", 5);
if (args.length <= 0)
return null;
String type = args[0];
boolean haveIP = true;
// no IP in these, replace port only
if (type == "RESUME" || type == "ACCEPT") {
haveIP = false;
} else if (!(type.equals("CHAT") || type.equals("SEND"))) {
if (ALLOW_ALL_DCC_IN) {
if (ctcp > 0)
return pfx + msg + (char) 0x01;
return pfx + msg;
}
return null;
}
if (helper == null || !helper.isEnabled())
return null;
if (args.length < 3)
return null;
if (haveIP && args.length < 4)
return null;
String arg = args[1];
int nextArg = 2;
String b32 = null;
if (haveIP)
b32 = args[nextArg++];
int cPort;
try {
String cp = args[nextArg++];
cPort = Integer.parseInt(cp);
} catch (NumberFormatException nfe) {
return null;
}
if (cPort < 0 || cPort > 65535)
return null;
int port = -1;
if (haveIP) {
if (cPort > 0)
port = helper.newIncoming(b32, cPort, type);
else
// "reverse/firewall DCC" - send it through without tracking
port = cPort;
} else if (type.equals("ACCEPT")) {
port = helper.acceptIncoming(cPort);
} else if (type.equals("RESUME")) {
port = helper.resumeIncoming(cPort);
}
if (port < 0)
return null;
StringBuilder buf = new StringBuilder(256);
buf.append(pfx)
.append(type).append(' ').append(arg).append(' ');
if (haveIP) {
if (port > 0) {
byte[] myIP = helper.getLocalAddress();
buf.append(DataHelper.fromLong(myIP, 0, myIP.length)).append(' ');
} else {
// "reverse/firewall DCC" - set dummy IP and send it through
buf.append("0 ");
}
}
buf.append(port);
while (args.length > nextArg) {
buf.append(' ').append(args[nextArg++]);
}
if (pfx.indexOf(0x01) >= 0)
buf.append((char) 0x01);
return buf.toString();
}
/**
*<pre>
* DCC CHAT chat IP port -> DCC CHAT chat xxx.b32.i2p i2p-port
* DCC SEND file IP port length -> DCC SEND file xxx.b32.i2p i2p-port length
* DCC RESUME file port offset -> DCC RESUME file i2p-port offset
* DCC ACCEPT file port offset -> DCC ACCEPT file i2p-port offset
* DCC xxx -> null
*</pre>
*
* @param pfx the message through the "DCC " part
* @param msg the message after the "DCC " part
* @param helper may be null
* @return the sanitized message or null to block
* @since 0.8.9
*/
private static String filterDCCOut(String pfx, String msg, DCCHelper helper) {
// strip trailing ctcp (other one is in pfx)
int ctcp = msg.indexOf(0x01);
if (ctcp > 0)
msg = msg.substring(0, ctcp);
String[] args = msg.split(" ", 5);
if (args.length <= 0)
return null;
String type = args[0];
boolean haveIP = true;
// no IP in these, replace port only
if (type == "RESUME" || type == "ACCEPT") {
haveIP = false;
} else if (!(type.equals("CHAT") || type.equals("SEND"))) {
if (ALLOW_ALL_DCC_OUT) {
if (ctcp > 0)
return pfx + msg + (char) 0x01;
return pfx + msg;
}
}
if (helper == null || !helper.isEnabled())
return null;
if (args.length < 3)
return null;
if (haveIP && args.length < 4)
return null;
String arg = args[1];
byte[] ip = null;
int nextArg = 2;
if (haveIP) {
try {
String ips = args[nextArg++];
long ipl = Long.parseLong(ips);
if (ipl < 0x01000000) {
// "reverse/firewall DCC"
// http://en.wikipedia.org/wiki/Direct_Client-to-Client
// xchat sends an IP of 199 and a port of 0
Log log = new Log(IRCFilter.class);
log.logAlways(Log.WARN, "Reverse / Firewall DCC, IP = 0x" + Long.toHexString(ipl));
//return null;
}
ip = DataHelper.toLong(4, ipl);
} catch (NumberFormatException nfe) {
return null;
}
}
int cPort;
try {
String cp = args[nextArg++];
cPort = Integer.parseInt(cp);
} catch (NumberFormatException nfe) {
return null;
}
if (cPort < 0 || cPort > 65535)
return null;
int port = -1;
if (haveIP) {
if (cPort > 0) {
// nonzero port but bogus IP? hmm. Fix IP and hope.
if (ip[0] == 0)
ip = new byte[] {127, 0, 0, 1};
port = helper.newOutgoing(ip, cPort, type);
} else {
// "reverse/firewall DCC" - send it through without tracking
Log log = new Log(IRCFilter.class);
log.logAlways(Log.WARN, "Reverse / Firewall DCC, port = 0");
port = cPort;
}
} else if (type.equals("ACCEPT")) {
port = helper.acceptOutgoing(cPort);
} else if (type.equals("RESUME")) {
port = helper.resumeOutgoing(cPort);
}
if (port < 0)
return null;
StringBuilder buf = new StringBuilder(256);
buf.append(pfx)
.append(type).append(' ').append(arg).append(' ');
if (haveIP) {
if (port > 0)
buf.append(helper.getB32Hostname()).append(' ');
else
// "reverse/firewall DCC" - set dummy IP and send it through
buf.append("0 ");
}
buf.append(port);
while (args.length > nextArg) {
buf.append(' ').append(args[nextArg++]);
}
if (pfx.indexOf(0x01) >= 0)
buf.append((char) 0x01);
return buf.toString();
}
}

View File

@ -0,0 +1,101 @@
package net.i2p.i2ptunnel.irc;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.util.Log;
/**
* Thread to do inbound filtering.
* Moved from I2PTunnelIRCClient.java
*
* @since 0.8.9
*/
public class IrcInboundFilter implements Runnable {
private final Socket local;
private final I2PSocket remote;
private final StringBuffer expectedPong;
private final Log _log;
private final DCCHelper _dccHelper;
public IrcInboundFilter(Socket lcl, I2PSocket rem, StringBuffer pong, Log log) {
this(lcl, rem, pong, log, null);
}
/**
* @param helper may be null
* @since 0.8.9
*/
public IrcInboundFilter(Socket lcl, I2PSocket rem, StringBuffer pong, Log log, DCCHelper helper) {
local = lcl;
remote = rem;
expectedPong = pong;
_log = log;
_dccHelper = helper;
}
public void run() {
// Todo: Don't use BufferedReader - IRC spec limits line length to 512 but...
BufferedReader in;
OutputStream output;
try {
in = new BufferedReader(new InputStreamReader(remote.getInputStream(), "ISO-8859-1"));
output=local.getOutputStream();
} catch (IOException e) {
if (_log.shouldLog(Log.ERROR))
_log.error("IrcInboundFilter: no streams",e);
return;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("IrcInboundFilter: Running.");
try {
while(true)
{
try {
String inmsg = in.readLine();
if(inmsg==null)
break;
if(inmsg.endsWith("\r"))
inmsg=inmsg.substring(0,inmsg.length()-1);
if (_log.shouldLog(Log.DEBUG))
_log.debug("in: [" + inmsg + "]");
String outmsg = IRCFilter.inboundFilter(inmsg, expectedPong, _dccHelper);
if(outmsg!=null)
{
if(!inmsg.equals(outmsg)) {
if (_log.shouldLog(Log.WARN)) {
_log.warn("inbound FILTERED: "+outmsg);
_log.warn(" - inbound was: "+inmsg);
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info("inbound: "+outmsg);
}
outmsg=outmsg+"\r\n"; // rfc1459 sec. 2.3
output.write(outmsg.getBytes("ISO-8859-1"));
// probably doesn't do much but can't hurt
output.flush();
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("inbound BLOCKED: "+inmsg);
}
} catch (IOException e1) {
if (_log.shouldLog(Log.WARN))
_log.warn("IrcInboundFilter: disconnected",e1);
break;
}
}
} catch (RuntimeException re) {
_log.error("Error filtering inbound data", re);
} finally {
try { local.close(); } catch (IOException e) {}
}
if(_log.shouldLog(Log.DEBUG))
_log.debug("IrcInboundFilter: Done.");
}
}

View File

@ -0,0 +1,101 @@
package net.i2p.i2ptunnel.irc;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.util.Log;
/**
* Thread to do outbound filtering.
* Moved from I2PTunnelIRCClient.java
*
* @since 0.8.9
*/
public class IrcOutboundFilter implements Runnable {
private final Socket local;
private final I2PSocket remote;
private final StringBuffer expectedPong;
private final Log _log;
private final DCCHelper _dccHelper;
public IrcOutboundFilter(Socket lcl, I2PSocket rem, StringBuffer pong, Log log) {
this(lcl, rem, pong, log, null);
}
/**
* @param helper may be null
* @since 0.8.9
*/
public IrcOutboundFilter(Socket lcl, I2PSocket rem, StringBuffer pong, Log log, DCCHelper helper) {
local = lcl;
remote = rem;
expectedPong = pong;
_log = log;
_dccHelper = helper;
}
public void run() {
// Todo: Don't use BufferedReader - IRC spec limits line length to 512 but...
BufferedReader in;
OutputStream output;
try {
in = new BufferedReader(new InputStreamReader(local.getInputStream(), "ISO-8859-1"));
output=remote.getOutputStream();
} catch (IOException e) {
if (_log.shouldLog(Log.ERROR))
_log.error("IrcOutboundFilter: no streams",e);
return;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("IrcOutboundFilter: Running.");
try {
while(true)
{
try {
String inmsg = in.readLine();
if(inmsg==null)
break;
if(inmsg.endsWith("\r"))
inmsg=inmsg.substring(0,inmsg.length()-1);
if (_log.shouldLog(Log.DEBUG))
_log.debug("out: [" + inmsg + "]");
String outmsg = IRCFilter.outboundFilter(inmsg, expectedPong, _dccHelper);
if(outmsg!=null)
{
if(!inmsg.equals(outmsg)) {
if (_log.shouldLog(Log.WARN)) {
_log.warn("outbound FILTERED: "+outmsg);
_log.warn(" - outbound was: "+inmsg);
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info("outbound: "+outmsg);
}
outmsg=outmsg+"\r\n"; // rfc1459 sec. 2.3
output.write(outmsg.getBytes("ISO-8859-1"));
// save 250 ms in streaming
output.flush();
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("outbound BLOCKED: "+"\""+inmsg+"\"");
}
} catch (IOException e1) {
if (_log.shouldLog(Log.WARN))
_log.warn("IrcOutboundFilter: disconnected",e1);
break;
}
}
} catch (RuntimeException re) {
_log.error("Error filtering outbound data", re);
} finally {
try { remote.close(); } catch (IOException e) {}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("IrcOutboundFilter: Done.");
}
}

View File

@ -11,7 +11,8 @@ import java.net.Socket;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelIRCClient;
import net.i2p.i2ptunnel.irc.IrcInboundFilter;
import net.i2p.i2ptunnel.irc.IrcOutboundFilter;
import net.i2p.i2ptunnel.Logging;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PAppThread;
@ -50,10 +51,10 @@ public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel {
Socket clientSock = serv.getClientSocket();
I2PSocket destSock = serv.getDestinationI2PSocket(this);
StringBuffer expectedPong = new StringBuffer();
Thread in = new I2PAppThread(new I2PTunnelIRCClient.IrcInboundFilter(clientSock, destSock, expectedPong, _log),
Thread in = new I2PAppThread(new IrcInboundFilter(clientSock, destSock, expectedPong, _log),
"SOCKS IRC Client " + (++__clientId) + " in", true);
in.start();
Thread out = new I2PAppThread(new I2PTunnelIRCClient.IrcOutboundFilter(clientSock, destSock, expectedPong, _log),
Thread out = new I2PAppThread(new IrcOutboundFilter(clientSock, destSock, expectedPong, _log),
"SOCKS IRC Client " + __clientId + " out", true);
out.start();
} catch (SOCKSException e) {

View File

@ -21,6 +21,7 @@ import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.I2PTunnelIRCClient;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
import net.i2p.util.Addresses;
@ -170,6 +171,11 @@ public class EditBean extends IndexBean {
return getBooleanProperty(tunnel, "i2cp.encryptLeaseSet");
}
/** @since 0.8.9 */
public boolean getDCC(int tunnel) {
return getBooleanProperty(tunnel, I2PTunnelIRCClient.PROP_DCC);
}
public String getEncryptKey(int tunnel) {
return getProperty(tunnel, "i2cp.leaseSetKey", "");
}

View File

@ -8,6 +8,7 @@ package net.i2p.i2ptunnel.web;
*
*/
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@ -27,9 +28,11 @@ import net.i2p.data.PrivateKeyFile;
import net.i2p.data.SessionKey;
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.I2PTunnelIRCClient;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
/**
@ -40,9 +43,9 @@ import net.i2p.util.Log;
* Usage by classes outside of i2ptunnel.war is deprecated.
*/
public class IndexBean {
protected I2PAppContext _context;
protected Log _log;
protected TunnelControllerGroup _group;
protected final I2PAppContext _context;
protected final Log _log;
protected final TunnelControllerGroup _group;
private String _action;
private int _tunnel;
//private long _prevNonce;
@ -74,8 +77,8 @@ public class IndexBean {
private boolean _sharedClient;
private boolean _privKeyGenerate;
private boolean _removeConfirmed;
private Set<String> _booleanOptions;
private Map<String, String> _otherOptions;
private final Set<String> _booleanOptions;
private final Map<String, String> _otherOptions;
private int _hashCashValue;
private int _certType;
private String _certSigner;
@ -198,17 +201,17 @@ public class IndexBean {
}
private String stopAll() {
if (_group == null) return "";
List msgs = _group.stopAllControllers();
List<String> msgs = _group.stopAllControllers();
return getMessages(msgs);
}
private String startAll() {
if (_group == null) return "";
List msgs = _group.startAllControllers();
List<String> msgs = _group.startAllControllers();
return getMessages(msgs);
}
private String restartAll() {
if (_group == null) return "";
List msgs = _group.restartAllControllers();
List<String> msgs = _group.restartAllControllers();
return getMessages(msgs);
}
private String reloadConfig() {
@ -316,6 +319,10 @@ public class IndexBean {
return rv;
}
/**
* Stop the tunnel, delete from config,
* rename the private key file if in the default directory
*/
private String deleteTunnel() {
if (!_removeConfirmed)
return "Please confirm removal";
@ -324,8 +331,38 @@ public class IndexBean {
if (cur == null)
return "Invalid tunnel number";
List msgs = _group.removeController(cur);
List<String> msgs = _group.removeController(cur);
msgs.addAll(doSave());
// Rename private key file if it was a default name in
// the default directory, so it doesn't get reused when a new
// tunnel is created.
// Use configured file name if available, not the one from the form.
String pk = cur.getPrivKeyFile();
if (pk == null)
pk = _privKeyFile;
if (pk != null && pk.startsWith("i2ptunnel") && pk.endsWith("-privKeys.dat")) {
File pkf = new File(_context.getConfigDir(), pk);
if (pkf.exists()) {
String name = cur.getName();
if (name == null) {
name = cur.getDescription();
if (name == null) {
name = cur.getType();
if (name == null)
name = Long.toString(_context.clock().now());
}
}
name = "i2ptunnel-deleted-" + name.replace(' ', '_') + "-privkeys.dat";
File to = new File(_context.getConfigDir(), name);
if (to.exists())
to = new File(_context.getConfigDir(), name + '-' + _context.clock().now());
boolean success = FileUtil.rename(pkf, to);
if (success)
msgs.add("Private key file " + pkf.getAbsolutePath() +
" renamed to " + to.getAbsolutePath());
}
}
return getMessages(msgs);
}
@ -675,6 +712,11 @@ public class IndexBean {
_booleanOptions.add("i2cp.encryptLeaseSet");
}
/** @since 0.8.9 */
public void setDCC(String moo) {
_booleanOptions.add(I2PTunnelIRCClient.PROP_DCC);
}
protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList";
protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList";
@ -838,7 +880,11 @@ public class IndexBean {
} else if (tun.getIsRunning() || tun.getIsStarting()) {
return "Tunnel must be stopped before modifying destination";
}
PrivateKeyFile pkf = new PrivateKeyFile(_privKeyFile);
File keyFile = new File(_privKeyFile);
if (!keyFile.isAbsolute())
keyFile = new File(_context.getConfigDir(), _privKeyFile);
PrivateKeyFile pkf = new PrivateKeyFile(keyFile);
try {
pkf.createIfAbsent();
} catch (Exception e) {
@ -980,13 +1026,28 @@ public class IndexBean {
else
config.setProperty("interface", "");
}
if ("ircclient".equals(_type)) {
boolean dcc = _booleanOptions.contains(I2PTunnelIRCClient.PROP_DCC);
config.setProperty("option." + I2PTunnelIRCClient.PROP_DCC,
"" + dcc);
// add some sane server options since they aren't in the GUI (yet)
if (dcc) {
config.setProperty("option." + PROP_MAX_CONNS_MIN, "3");
config.setProperty("option." + PROP_MAX_CONNS_HOUR, "10");
config.setProperty("option." + PROP_MAX_TOTAL_CONNS_MIN, "5");
config.setProperty("option." + PROP_MAX_TOTAL_CONNS_HOUR, "25");
}
}
return config;
}
private static final String _noShowOpts[] = {
"inbound.length", "outbound.length", "inbound.lengthVariance", "outbound.lengthVariance",
"inbound.backupQuantity", "outbound.backupQuantity", "inbound.quantity", "outbound.quantity",
"inbound.nickname", "outbound.nickname", "i2p.streaming.connectDelay", "i2p.streaming.maxWindowSize"
"inbound.nickname", "outbound.nickname", "i2p.streaming.connectDelay", "i2p.streaming.maxWindowSize",
I2PTunnelIRCClient.PROP_DCC
};
private static final String _booleanClientOpts[] = {
"i2cp.reduceOnIdle", "i2cp.closeOnIdle", "i2cp.newDestOnResume", "persistentClientKey", "i2cp.delayOpen"
@ -1008,6 +1069,7 @@ public class IndexBean {
PROP_MAX_TOTAL_CONNS_MIN, PROP_MAX_TOTAL_CONNS_HOUR, PROP_MAX_TOTAL_CONNS_DAY,
PROP_MAX_STREAMS
};
protected static final Set _noShowSet = new HashSet(64);
static {
_noShowSet.addAll(Arrays.asList(_noShowOpts));

View File

@ -1,13 +1,17 @@
<%@page pageEncoding="UTF-8"%>
<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean" %><%
<%
// NOTE: Do the header carefully so there is no whitespace before the <?xml... line
%><%@page pageEncoding="UTF-8"
%><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
%><%
String tun = request.getParameter("tunnel");
if (tun != null) {
try {
int curTunnel = Integer.parseInt(tun);
if (EditBean.staticIsClient(curTunnel)) {
%><jsp:include page="editClient.jsp" /><%
%><jsp:include page="editClient.jsp" /><%
} else {
%><jsp:include page="editServer.jsp" /><%
%><jsp:include page="editServer.jsp" /><%
}
} catch (NumberFormatException nfe) {
%>Invalid tunnel parameter<%
@ -16,9 +20,9 @@ String tun = request.getParameter("tunnel");
String type = request.getParameter("type");
int curTunnel = -1;
if (EditBean.isClient(type)) {
%><jsp:include page="editClient.jsp" /><%
%><jsp:include page="editClient.jsp" /><%
} else {
%><jsp:include page="editServer.jsp" /><%
%><jsp:include page="editServer.jsp" /><%
}
}
%>

View File

@ -173,6 +173,15 @@
<input value="1" type="checkbox" id="startOnLoad" name="startOnLoad" title="Start Tunnel Automatically"<%=(editBean.startAutomatically(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<span class="comment"><%=intl._("(Check the Box for 'YES')")%></span>
</div>
<% if ("ircclient".equals(tunnelType)) { %>
<div id="startupField" class="rowItem">
<label for="dcc" accesskey="d">
<%=intl._("Enable DCC")%>:
</label>
<input value="1" type="checkbox" id="startOnLoad" name="DCC" title="Enable DCC"<%=(editBean.getDCC(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
<span class="comment"><%=intl._("(Check the Box for 'YES')")%></span>
</div>
<% } // ircclient %>
<div class="footer">
</div>

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