Compare commits

..

1 Commits

Author SHA1 Message Date
idk
0e8e8480ea Patch for family key issue in 1.8.0 affecting Android 2022-06-17 03:07:37 -04:00
1109 changed files with 97662 additions and 143303 deletions

View File

@ -29,4 +29,3 @@ installer/build
router/java/build
router/build
override.properties

View File

@ -5,11 +5,6 @@ name: Java CI
on: [push]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
@ -17,9 +12,9 @@ jobs:
steps:
- name: GetText
run: sudo apt install gettext
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: Set up JDK 8
uses: actions/setup-java@v4
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: 'temurin'
@ -31,92 +26,9 @@ jobs:
- name: build with Ant
run: ant distclean pkg
- name: Upload installer.jar
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v2
with:
name: I2P-install-${{ github.sha }}.jar
name: I2P-install.jar-${{ github.sha }}
path: install.jar
javadoc-latest:
runs-on: ubuntu-latest
steps:
- name: Setup Pages
uses: actions/configure-pages@v4
- name: GetText
run: sudo apt install gettext
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name : Generate override.properties
run: |
rm -f override.properties
echo "build.built-by=GitHub Actions" >> override.properties
echo "noExe=true" >> override.properties
- name: test Debian build with Ant
run: ant distclean
- name: build javadoc with Ant
run: ant distclean javadoc updater
- name: zip javadoc
run: cp i2pupdate.zip build/javadoc/i2pupdate.zip && zip -r javadoc.zip build/javadoc
- name: Upload javadoc.zip
uses: actions/upload-artifact@v4
with:
name: I2P-javadoc-${{ github.sha }}.zip
path: javadoc.zip
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload javadocs to github page
path: 'build/javadoc'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
build-java7:
runs-on: ubuntu-latest
steps:
- name: GetText
run: sudo apt install gettext
- uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
java-version: '8'
distribution: 'temurin'
- name : Generate override.properties
run: |
git clone https://github.com/eyedeekay/openjdk-7 "$HOME/openjdk-7"
rm -f override.properties
echo "build.built-by=GitHub Actions" >> override.properties
echo "noExe=true" >> override.properties
echo "javac.compilerargs=-bootclasspath $HOME/openjdk-7/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar:$HOME/openjdk-7/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/jce.jar -Xlint:all" >> override.properties
- name: build Maven dev build with Ant
run: ./installer/resources/maven-dev-release.sh 1
- name: Upload servlet-i2p.jar
uses: actions/upload-artifact@v4
with:
name: servlet-i2p-${{ github.sha }}.jar
path: pkg-mavencentral/servlet-i2p*.jar
- name: Upload streaming.jar
uses: actions/upload-artifact@v4
with:
name: streaming-${{ github.sha }}.jar
path: pkg-mavencentral/streaming*.jar
- name: Upload mstreaming.jar
uses: actions/upload-artifact@v4
with:
name: mstreaming-${{ github.sha }}.jar
path: pkg-mavencentral/mstreaming*.jar
- name: Upload router.jar
uses: actions/upload-artifact@v4
with:
name: router-${{ github.sha }}.jar
path: pkg-mavencentral/router*.jar
- name: Upload i2p.jar
uses: actions/upload-artifact@v4
with:
name: i2p-${{ github.sha }}.jar
path: pkg-mavencentral/i2p*.jar

View File

@ -1,23 +0,0 @@
# File: .github/workflows/repo-sync.yml
on:
schedule:
- cron: "*/5 * * * *"
workflow_dispatch:
jobs:
repo-sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: repo-sync
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: repo-sync/github-sync@v2
with:
source_repo: "https://i2pgit.org/i2p-hackers/i2p.i2p"
source_branch: "master"
destination_branch: "master"
github_token: ${{ secrets.PAT }}

View File

@ -1,65 +0,0 @@
name: mirror
on:
push:
tags:
- 'i2p-*.*.*'
jobs:
dl:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: |
changelog.txt
- name: download release artifacts
run: |
sudo apt-get install wget ca-certificates gpg sed curl git
git pull --tags
while true; do sleep 60m; wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')_windows.exe && break; done
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/I2P-Easy-Install-Bundle-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')-signed.exe
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/I2P-Easy-Install-Bundle-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').exe
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').jar
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').jar.sig
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')_windows.exe
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')_windows.exe.sig
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2psource_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').tar.bz2
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2psource_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').tar.bz2.sig
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').su3
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').su3.torrent
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate.su3
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').zip
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').zip.sig'
echo "$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')" > CHANGES.md
echo "===========" >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
curl https://raw.githubusercontent.com/i2p/i2p.newsxml/master/data/entries.html | sed -n '/<article/,/<\/article/p' | sed -n '1,/<\/article>/p' | sed -n '/<\/details>/,$p' | sed '1d' | sed 's/<\/\{0,1\}p>//g' | sed 's|<\/article>||g' >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
echo '```' >> CHANGES.md
head -n 25 changelog.txt >> CHANGES.md
echo '```' >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
echo "## Checksums" >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
echo '```' >> CHANGES.md
sha256sum * >> CHANGES.md
echo '```' >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
echo '```' >> CHANGES.md
file * >> CHANGES.md
echo '```' >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
cat CHANGES.md
- name: Upload artifacts
uses: ncipollo/release-action@v1
with:
artifacts: "*"
skipIfReleaseExists: true
bodyFile: "CHANGES.md"

2
.gitignore vendored
View File

@ -61,5 +61,3 @@ sloccount.sc
# TODO: why does this file appear?
apps/routerconsole/jsp/favicon.ico
.tx
/*.sh

View File

@ -52,7 +52,6 @@ test:ant:
- echo junit.home=/usr/share/java >> override.properties
- echo hamcrest.home=/usr/share/java >> override.properties
- echo mockito.home=/usr/share/java >> override.properties
- echo build.built-by=GitHub Actions >> override.properties
script:
- ant test
only:
@ -60,55 +59,19 @@ test:ant:
- merge_requests
- tags
test:javadoc:
stage: test
image: debian:unstable-slim
variables:
SCALA: https://downloads.lightbend.com/scala/2.12.13/scala-2.12.13.deb
LIBPREFIX: /usr/share/scala/lib
LIB_SCALATEST: https://repo1.maven.org/maven2/org/scalatest/scalatest_2.12/3.0.4/scalatest_2.12-3.0.4.jar
LIB_SCALACTIC: https://repo1.maven.org/maven2/org/scalactic/scalactic_2.12/3.0.4/scalactic_2.12-3.0.4.jar
before_script:
# Fix bug installing openjdk-11-jdk-headless's manuals
- mkdir -p /usr/share/man/man1/
- apt-get update -q
- apt-get install -y wget gettext
ant openjdk-21-jdk-headless
libmockito-java libhamcrest-java junit4
# Install specific version of scala
- wget -qO scala.deb "${SCALA}"
- dpkg -i scala.deb
# link to the scala libs with the name `ant test` expects
- ln -s "${LIBPREFIX}/scala-xml_2.12-1.0.6.jar" "${LIBPREFIX}/scala-xml.jar"
# Download required scala libs
- wget -qO "${LIBPREFIX}/scalactic.jar" "${LIB_SCALACTIC}"
- wget -qO "${LIBPREFIX}/scalatest.jar" "${LIB_SCALATEST}"
# Point ant to the right directories
- echo scalatest.libs=/usr/share/scala/lib > override.properties
- echo junit.home=/usr/share/java >> override.properties
- echo hamcrest.home=/usr/share/java >> override.properties
- echo mockito.home=/usr/share/java >> override.properties
- echo build.built-by=GitHub Actions >> override.properties
script:
- ant javadoc
only:
- master
- merge_requests
- tags
# Make sure we can build a docker image
# It's cached for later jobs
build_docker:
stage: build
image: docker:24.0.7
image: docker:19.03.12
services:
- docker:24.0.7-dind
- docker:19.03.12-dind
script:
# Try to load latest branch image from local tar or from registry
- docker load -i ci-exports/$CI_COMMIT_REF_SLUG.tar || docker pull $CI_REGISTRY_IMAGE:latest || true
- docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:latest .
- mkdir -p ci-exports/
- echo docker save $CI_REGISTRY_IMAGE:latest > ci-exports/$CI_COMMIT_REF_SLUG.tar
- docker save $CI_REGISTRY_IMAGE:latest > ci-exports/$CI_COMMIT_REF_SLUG.tar
variables:
# When using dind service, we need to instruct docker to talk with
# the daemon started inside of the service. The daemon is available
@ -126,7 +89,7 @@ build_docker:
# container, thanks to volume mount from config.toml
DOCKER_TLS_CERTDIR: "/certs"
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
# DOCKER_HOST: tcp://docker:2376
DOCKER_HOST: tcp://docker:2376
cache:
# The same key should be used across branches
key: "$CI_COMMIT_REF_SLUG"

View File

@ -1,12 +1,7 @@
;; warning - conversions for all Java bundles:
;; id->in, he->iw, iy, yi->ji
[main]
host = https://www.transifex.com
lang_map = ru_RU: ru, sv_SE: sv, tr_TR: tr, uk_UA: uk, zh_CN: zh, et_EE: et, id: in, he: iw
[o:otf:p:I2P:r:i2ptunnel]
file_filter = apps/i2ptunnel/locale/messages_<lang>.po
[I2P.i2ptunnel]
source_file = apps/i2ptunnel/locale/messages_en.po
source_lang = en
trans.ar = apps/i2ptunnel/locale/messages_ar.po
@ -14,7 +9,6 @@ trans.cs = apps/i2ptunnel/locale/messages_cs.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.es_AR = apps/i2ptunnel/locale/messages_es_AR.po
trans.fa = apps/i2ptunnel/locale/messages_fa.po
trans.fi = apps/i2ptunnel/locale/messages_fi.po
trans.fr = apps/i2ptunnel/locale/messages_fr.po
@ -41,8 +35,7 @@ trans.vi = apps/i2ptunnel/locale/messages_vi.po
trans.zh_CN = apps/i2ptunnel/locale/messages_zh.po
trans.zh_TW = apps/i2ptunnel/locale/messages_zh_TW.po
[o:otf:p:I2P:r:proxy]
file_filter = apps/i2ptunnel/locale-proxy/messages_<lang>.po
[I2P.proxy]
source_file = apps/i2ptunnel/locale-proxy/messages_en.po
source_lang = en
trans.ar = apps/i2ptunnel/locale-proxy/messages_ar.po
@ -50,7 +43,6 @@ trans.cs = apps/i2ptunnel/locale-proxy/messages_cs.po
trans.de = apps/i2ptunnel/locale-proxy/messages_de.po
trans.el = apps/i2ptunnel/locale-proxy/messages_el.po
trans.es = apps/i2ptunnel/locale-proxy/messages_es.po
trans.es_AR = apps/i2ptunnel/locale-proxy/messages_es_AR.po
trans.fa = apps/i2ptunnel/locale-proxy/messages_fa.po
trans.fi = apps/i2ptunnel/locale-proxy/messages_fi.po
trans.fr = apps/i2ptunnel/locale-proxy/messages_fr.po
@ -76,8 +68,7 @@ trans.vi = apps/i2ptunnel/locale-proxy/messages_vi.po
trans.zh_CN = apps/i2ptunnel/locale-proxy/messages_zh.po
trans.zh_TW = apps/i2ptunnel/locale-proxy/messages_zh_TW.po
[o:otf:p:I2P:r:core]
file_filter = core/locale/messages_<lang>.po
[I2P.core]
type = PO
source_file = core/locale/messages_en.po
source_lang = en
@ -115,8 +106,7 @@ trans.vi = core/locale/messages_vi.po
trans.zh_CN = core/locale/messages_zh.po
trans.zh_TW = core/locale/messages_zh_TW.po
[o:otf:p:I2P:r:router]
file_filter = router/locale/messages_<lang>.po
[I2P.router]
type = PO
source_file = router/locale/messages_en.po
source_lang = en
@ -127,7 +117,6 @@ trans.da = router/locale/messages_da.po
trans.de = router/locale/messages_de.po
trans.el = router/locale/messages_el.po
trans.es = router/locale/messages_es.po
trans.es_AR = router/locale/messages_es_AR.po
trans.et_EE = router/locale/messages_et.po
trans.fa = router/locale/messages_fa.po
trans.fi = router/locale/messages_fi.po
@ -155,8 +144,7 @@ trans.vi = router/locale/messages_vi.po
trans.zh_CN = router/locale/messages_zh.po
trans.zh_TW = router/locale/messages_zh_TW.po
[o:otf:p:I2P:r:routerconsole]
file_filter = apps/routerconsole/locale/messages_<lang>.po
[I2P.routerconsole]
source_file = apps/routerconsole/locale/messages_en.po
source_lang = en
trans.ar = apps/routerconsole/locale/messages_ar.po
@ -166,7 +154,6 @@ trans.da = apps/routerconsole/locale/messages_da.po
trans.de = apps/routerconsole/locale/messages_de.po
trans.el = apps/routerconsole/locale/messages_el.po
trans.es = apps/routerconsole/locale/messages_es.po
trans.es_AR = apps/routerconsole/locale/messages_es_AR.po
trans.et_EE = apps/routerconsole/locale/messages_et.po
trans.fa = apps/routerconsole/locale/messages_fa.po
trans.fi = apps/routerconsole/locale/messages_fi.po
@ -191,8 +178,7 @@ trans.vi = apps/routerconsole/locale/messages_vi.po
trans.zh_CN = apps/routerconsole/locale/messages_zh.po
trans.zh_TW = apps/routerconsole/locale/messages_zh_TW.po
[o:otf:p:I2P:r:welcome]
file_filter = apps/routerconsole/locale-news/messages_<lang>.po
[I2P.welcome]
source_file = apps/routerconsole/locale-news/messages_en.po
source_lang = en
trans.ar = apps/routerconsole/locale-news/messages_ar.po
@ -201,7 +187,6 @@ trans.cs = apps/routerconsole/locale-news/messages_cs.po
trans.de = apps/routerconsole/locale-news/messages_de.po
trans.el = apps/routerconsole/locale-news/messages_el.po
trans.es = apps/routerconsole/locale-news/messages_es.po
trans.es_AR = apps/routerconsole/locale-news/messages_es_AR.po
trans.fa = apps/routerconsole/locale-news/messages_fa.po
trans.fi = apps/routerconsole/locale-news/messages_fi.po
trans.fr = apps/routerconsole/locale-news/messages_fr.po
@ -234,8 +219,7 @@ trans.uk_UA = apps/routerconsole/locale-news/messages_uk.po
trans.zh_CN = apps/routerconsole/locale-news/messages_zh.po
trans.zh_TW = apps/routerconsole/locale-news/messages_zh_TW.po
[o:otf:p:I2P:r:countries]
file_filter = apps/routerconsole/locale-countries/messages_<lang>.po
[I2P.countries]
type = PO
source_file = apps/routerconsole/locale-countries/messages_en.po
source_lang = en
@ -248,7 +232,6 @@ trans.da = apps/routerconsole/locale-countries/messages_da.po
trans.de = apps/routerconsole/locale-countries/messages_de.po
trans.el = apps/routerconsole/locale-countries/messages_el.po
trans.es = apps/routerconsole/locale-countries/messages_es.po
trans.es_AR = apps/routerconsole/locale-countries/messages_es_AR.po
trans.et_EE = apps/routerconsole/locale-countries/messages_et.po
trans.fa = apps/routerconsole/locale-countries/messages_fa.po
trans.fi = apps/routerconsole/locale-countries/messages_fi.po
@ -285,17 +268,14 @@ trans.vi = apps/routerconsole/locale-countries/messages_vi.po
trans.zh_CN = apps/routerconsole/locale-countries/messages_zh.po
trans.zh_TW = apps/routerconsole/locale-countries/messages_zh_TW.po
[o:otf:p:I2P:r:i2psnark]
file_filter = apps/i2psnark/locale/messages_<lang>.po
[I2P.i2psnark]
source_file = apps/i2psnark/locale/messages_en.po
source_lang = en
trans.ar = apps/i2psnark/locale/messages_ar.po
trans.cs = apps/i2psnark/locale/messages_cs.po
trans.da = apps/i2psnark/locale/messages_da.po
trans.de = apps/i2psnark/locale/messages_de.po
trans.el = apps/i2psnark/locale/messages_el.po
trans.es = apps/i2psnark/locale/messages_es.po
trans.es_AR = apps/i2psnark/locale/messages_es_AR.po
trans.fa = apps/i2psnark/locale/messages_fa.po
trans.fi = apps/i2psnark/locale/messages_fi.po
trans.fr = apps/i2psnark/locale/messages_fr.po
@ -321,8 +301,7 @@ trans.vi = apps/i2psnark/locale/messages_vi.po
trans.zh_CN = apps/i2psnark/locale/messages_zh.po
trans.zh_TW = apps/i2psnark/locale/messages_zh_TW.po
[o:otf:p:I2P:r:susidns]
file_filter = apps/susidns/locale/messages_<lang>.po
[I2P.susidns]
source_file = apps/susidns/locale/messages_en.po
source_lang = en
trans.ar = apps/susidns/locale/messages_ar.po
@ -331,7 +310,6 @@ trans.da = apps/susidns/locale/messages_da.po
trans.de = apps/susidns/locale/messages_de.po
trans.el = apps/susidns/locale/messages_el.po
trans.es = apps/susidns/locale/messages_es.po
trans.es_AR = apps/susidns/locale/messages_es_AR.po
trans.fa = apps/susidns/locale/messages_fa.po
trans.fi = apps/susidns/locale/messages_fi.po
trans.fr = apps/susidns/locale/messages_fr.po
@ -355,8 +333,7 @@ trans.vi = apps/susidns/locale/messages_vi.po
trans.zh_CN = apps/susidns/locale/messages_zh.po
trans.zh_TW = apps/susidns/locale/messages_zh_TW.po
[o:otf:p:I2P:r:desktopgui]
file_filter = apps/desktopgui/locale/messages_<lang>.po
[I2P.desktopgui]
source_file = apps/desktopgui/locale/messages_en.po
source_lang = en
trans.ar = apps/desktopgui/locale/messages_ar.po
@ -400,8 +377,7 @@ trans.vi = apps/desktopgui/locale/messages_vi.po
trans.zh_CN = apps/desktopgui/locale/messages_zh.po
trans.zh_TW = apps/desktopgui/locale/messages_zh_TW.po
[o:otf:p:I2P:r:susimail]
file_filter = apps/susimail/locale/messages_<lang>.po
[I2P.susimail]
source_file = apps/susimail/locale/messages_en.po
source_lang = en
trans.ar = apps/susimail/locale/messages_ar.po
@ -413,8 +389,6 @@ trans.da = apps/susimail/locale/messages_da.po
trans.de = apps/susimail/locale/messages_de.po
trans.el = apps/susimail/locale/messages_el.po
trans.es = apps/susimail/locale/messages_es.po
trans.es_AR = apps/susimail/locale/messages_es_AR.po
trans.et_EE = apps/susimail/locale/messages_et.po
trans.fa = apps/susimail/locale/messages_fa.po
trans.fi = apps/susimail/locale/messages_fi.po
trans.fr = apps/susimail/locale/messages_fr.po
@ -428,7 +402,6 @@ trans.id = apps/susimail/locale/messages_in.po
trans.it = apps/susimail/locale/messages_it.po
trans.ja = apps/susimail/locale/messages_ja.po
trans.ko = apps/susimail/locale/messages_ko.po
trans.ku = apps/susimail/locale/messages_ku.po
trans.mg = apps/susimail/locale/messages_mg.po
trans.nb = apps/susimail/locale/messages_nb.po
trans.nl = apps/susimail/locale/messages_nl.po
@ -438,7 +411,6 @@ trans.pt_BR = apps/susimail/locale/messages_pt_BR.po
trans.ro = apps/susimail/locale/messages_ro.po
trans.ru_RU = apps/susimail/locale/messages_ru.po
trans.sk = apps/susimail/locale/messages_sk.po
trans.sl = apps/susimail/locale/messages_sl.po
trans.sq = apps/susimail/locale/messages_sq.po
trans.sr = apps/susimail/locale/messages_sr.po
trans.sv_SE = apps/susimail/locale/messages_sv.po
@ -448,8 +420,7 @@ trans.vi = apps/susimail/locale/messages_vi.po
trans.zh_CN = apps/susimail/locale/messages_zh.po
trans.zh_TW = apps/susimail/locale/messages_zh_TW.po
[o:otf:p:I2P:r:debconf]
file_filter = debian/po/<lang>.po
[I2P.debconf]
source_file = debian/po/templates.pot
source_lang = en
trans.ar = debian/po/ar.po
@ -458,7 +429,6 @@ trans.cs = debian/po/cs.po
trans.de = debian/po/de.po
trans.el = debian/po/el.po
trans.es = debian/po/es.po
trans.es_AR = debian/po/es_AR.po
trans.fi = debian/po/fi.po
trans.fr = debian/po/fr.po
trans.gl = debian/po/gl.po
@ -484,20 +454,16 @@ trans.uk_UA = debian/po/uk.po
trans.zh_CN = debian/po/zh.po
trans.zh_TW = debian/po/zh_TW.po
[o:otf:p:I2P:r:i2prouter-script]
file_filter = installer/resources/locale/po/messages_<lang>.po
[I2P.i2prouter-script]
source_file = installer/resources/locale/po/messages_en.po
source_lang = en
trans.ar = installer/resources/locale/po/messages_ar.po
trans.az = installer/resources/locale/po/messages_az.po
trans.ca = installer/resources/locale/po/messages_ca.po
trans.cs = installer/resources/locale/po/messages_cs.po
trans.de = installer/resources/locale/po/messages_de.po
trans.es = installer/resources/locale/po/messages_es.po
trans.es_AR = installer/resources/locale/po/messages_es_AR.po
trans.fi = installer/resources/locale/po/messages_fi.po
trans.fr = installer/resources/locale/po/messages_fr.po
trans.hu = installer/resources/locale/po/messages_hu.po
trans.id = installer/resources/locale/po/messages_id.po
trans.it = installer/resources/locale/po/messages_it.po
trans.ja = installer/resources/locale/po/messages_ja.po
@ -516,7 +482,7 @@ trans.uk_UA = installer/resources/locale/po/messages_uk.po
trans.zh_CN = installer/resources/locale/po/messages_zh.po
trans.zh_TW = installer/resources/locale/po/messages_zh_TW.po
[o:otf:p:I2P:r:getopt]
[I2P.getopt]
;;
;; Java properties files (when not read with our DataHelper methods) must be ISO-8859-1 encoded.
;; See https://docs.oracle.com/javase/6/docs/api/java/util/Properties.html
@ -533,7 +499,6 @@ trans.zh_TW = installer/resources/locale/po/messages_zh_TW.po
;; and should be escaped using native2ascii after downloading:
;; gl, pt, pt_BR, sq, sv, tr
;;
file_filter = core/java/src/gnu/getopt/MessagesBundle_<lang>.properties
source_file = core/java/src/gnu/getopt/MessagesBundle.properties
source_lang = en
type = PROPERTIES
@ -542,7 +507,6 @@ trans.az = core/java/src/gnu/getopt/MessagesBundle_az.properties
trans.cs = core/java/src/gnu/getopt/MessagesBundle_cs.properties
trans.de = core/java/src/gnu/getopt/MessagesBundle_de.properties
trans.es = core/java/src/gnu/getopt/MessagesBundle_es.properties
trans.es_AR = core/java/src/gnu/getopt/MessagesBundle_es_AR.properties
trans.fi = core/java/src/gnu/getopt/MessagesBundle_fi.properties
trans.fr = core/java/src/gnu/getopt/MessagesBundle_fr.properties
trans.gl = core/java/src/gnu/getopt/MessagesBundle_gl.properties
@ -570,8 +534,7 @@ trans.uk_UA = core/java/src/gnu/getopt/MessagesBundle_uk.properties
trans.zh_CN = core/java/src/gnu/getopt/MessagesBundle_zh.properties
trans.zh_TW = core/java/src/gnu/getopt/MessagesBundle_zh_TW.properties
[o:otf:p:I2P:r:streaming]
file_filter = apps/ministreaming/locale/messages_<lang>.po
[I2P.streaming]
source_file = apps/ministreaming/locale/messages_en.po
source_lang = en
trans.ar = apps/ministreaming/locale/messages_ar.po
@ -580,7 +543,6 @@ trans.ca = apps/ministreaming/locale/messages_ca.po
trans.cs = apps/ministreaming/locale/messages_cs.po
trans.de = apps/ministreaming/locale/messages_de.po
trans.es = apps/ministreaming/locale/messages_es.po
trans.es_AR = apps/ministreaming/locale/messages_es_AR.po
trans.fa = apps/ministreaming/locale/messages_fa.po
trans.fi = apps/ministreaming/locale/messages_fi.po
trans.fr = apps/ministreaming/locale/messages_fr.po
@ -589,7 +551,6 @@ trans.hu = apps/ministreaming/locale/messages_hu.po
;; Java converts id to in
trans.id = apps/ministreaming/locale/messages_in.po
trans.it = apps/ministreaming/locale/messages_it.po
trans.ja = apps/ministreaming/locale/messages_ja.po
trans.ko = apps/ministreaming/locale/messages_ko.po
trans.nb = apps/ministreaming/locale/messages_nb.po
trans.nl = apps/ministreaming/locale/messages_nl.po
@ -606,12 +567,11 @@ trans.uk_UA = apps/ministreaming/locale/messages_uk.po
trans.zh_CN = apps/ministreaming/locale/messages_zh.po
trans.zh_TW = apps/ministreaming/locale/messages_zh_TW.po
[o:otf:p:I2P:r:manpages]
[I2P.manpages]
;;
;; after adding languages here, add to debian/*.manpages also
;; You must run installer/resources/poupdate-man.sh first.
;;
file_filter = installer/resources/locale-man/man_<lang>.po
type = PO
source_file = installer/resources/locale-man/man.pot
source_lang = en
@ -619,7 +579,6 @@ trans.ar = installer/resources/locale-man/man_ar.po
trans.az = installer/resources/locale-man/man_az.po
trans.de = installer/resources/locale-man/man_de.po
trans.es = installer/resources/locale-man/man_es.po
trans.es_AR = installer/resources/locale-man/man_es_AR.po
trans.fi = installer/resources/locale-man/man_fi.po
trans.fr = installer/resources/locale-man/man_fr.po
trans.hu = installer/resources/locale-man/man_hu.po
@ -638,13 +597,12 @@ trans.tr_TR = installer/resources/locale-man/man_tr.po
trans.zh_CN = installer/resources/locale-man/man_zh.po
trans.zh_TW = installer/resources/locale-man/man_zh_TW.po
[o:otf:p:I2P:r:eepsite]
[I2P.eepsite]
;;
;; For any new translations, add links in installer/resources/eepsite/docroot/help/index.html
;; and copy new flags in build.xml copyflags-unlesspkg target,
;; and add to debian/i2p-router.links and debian-alt/*/i2p-router.links
;;
file_filter = installer/resources/eepsite/docroot/help/index_<lang>.po
type = HTML
source_file = installer/resources/eepsite/docroot/help/index.html
source_lang = en
@ -654,14 +612,14 @@ source_lang = en
trans.az = installer/resources/eepsite/docroot/help/index_az.html
trans.de = installer/resources/eepsite/docroot/help/index_de.html
trans.el = installer/resources/eepsite/docroot/help/index_el.html
trans.es = installer/resources/eepsite/docroot/help/index_es.html
;; not yet translated on TX, use old page
;;trans.es = installer/resources/eepsite/docroot/help/index_es.html
trans.fa = installer/resources/eepsite/docroot/help/index_fa.html
trans.fr = installer/resources/eepsite/docroot/help/index_fr.html
trans.hu = installer/resources/eepsite/docroot/help/index_hu.html
;; Java converts id to in
trans.id = installer/resources/eepsite/docroot/help/index_in.html
trans.it = installer/resources/eepsite/docroot/help/index_it.html
trans.ja = installer/resources/eepsite/docroot/help/index_ja.html
;; not yet translated on TX, use old page
;;trans.nl = installer/resources/eepsite/docroot/help/index_nl.html
trans.pl = installer/resources/eepsite/docroot/help/index_pl.html
@ -673,19 +631,14 @@ trans.tr_TR = installer/resources/eepsite/docroot/help/index_tr.html
trans.uk_UA = installer/resources/eepsite/docroot/help/index_uk.html
trans.zh_CN = installer/resources/eepsite/docroot/help/index_zh.html
[o:otf:p:I2P:r:readme]
[I2P.readme]
;;
;; Text on /console
;;
;; NOTE: No support for country suffixes right now.
;; See ResourceHelper.java
;;
file_filter = apps/routerconsole/resources/docs/readme_<lang>.html
type = HTML
source_file = apps/routerconsole/resources/docs/readme.html
source_lang = en
trans.ar = apps/routerconsole/resources/docs/readme_ar.html
trans.cs = apps/routerconsole/resources/docs/readme_cs.html
trans.de = apps/routerconsole/resources/docs/readme_de.html
trans.fr = apps/routerconsole/resources/docs/readme_fr.html
trans.hu = apps/routerconsole/resources/docs/readme_hu.html
@ -703,3 +656,6 @@ trans.uk_UA = apps/routerconsole/resources/docs/readme_uk.html
trans.zh_CN = apps/routerconsole/resources/docs/readme_zh.html
trans.zh_TW = apps/routerconsole/resources/docs/readme_zh_TW.html
[main]
host = https://www.transifex.com

View File

@ -10,12 +10,7 @@ version: "3.5"
services:
i2p:
image: geti2p/i2p
ports:
- 127.0.0.1:4444:4444
- 127.0.0.1:6668:6668
- 127.0.0.1:7657:7657
- 54321:12345
- 54321:12345/udp
network_mode: host
volumes:
- ./i2pconfig:/i2p/.i2p
- ./i2ptorrents:/i2psnark
@ -28,22 +23,11 @@ Note that this quick-start approach is not recommended for production deployment
### Building an image
There is an i2P image available over at [DockerHub](https://hub.docker.com). If you do not want to use that one, you can build one yourself:
```
docker build -t geti2p/i2p .
docker build -t i2p .
```
### Running a container
#### Environment Variables
It is possible to set the IP address where the I2P router is accessible by setting
the `IP_ADDR` environment variable in your `docker run` command or your `docker-compose`
file. For example, if you want to make your I2P router listen on all addresses, then
you should pass `-e IP_ADDR=0.0.0.0` to your `docker run` command.
It is also possible to configure the memory available to the I2P router using
environment variables. To do this, use the: `JVM_XMX` environment variable by passing,
for example, `-e JVM_XMX=256m`.
#### Volumes
The container requires a volume for the configuration data to be mounted. Optionally, you can mount a separate volume for torrent ("i2psnark") downloads. See the example below.
@ -75,19 +59,16 @@ A best-practices guide for cloud deployments is beyond the scope of this documen
#### Example
Here is an example container that mounts `i2phome` as home directory, `i2ptorrents` for torrents, and opens HTTP Proxy, IRC, Router Console and I2NP Protocols. It also limits the memory available to the JVM to 256MB.
```
docker build -t geti2p/i2p .
# I2NP port needs TCP and UDP. Change the 54321 to something random, greater than 1024.
docker run \
-e JVM_XMX=256m \
-v i2phome:/i2p/.i2p \
-v i2ptorrents:/i2psnark \
-p 127.0.0.1:4444:4444 \
-p 127.0.0.1:6668:6668 \
-p 127.0.0.1:7657:7657 \
-p 4444:4444 \
-p 6668:6668 \
-p 7657:7657 \
-p 54321:12345 \
-p 54321:12345/udp \
geti2p/i2p:latest
-p 54321:12345/udp \ # I2NP port needs TCP and UDP. Change the 54321 to something random, greater than 1024.
i2p:latest
```

View File

@ -1,27 +1,24 @@
FROM alpine:3.17.1 as builder
FROM jlesage/baseimage:alpine-3.15-glibc as builder
ENV APP_HOME="/i2p"
WORKDIR /tmp/build
COPY . .
RUN apk add --virtual build-base gettext tar bzip2 apache-ant openjdk17 \
&& echo "build.built-by=Docker" >> override.properties \
RUN add-pkg --virtual build-base gettext tar bzip2 apache-ant openjdk8 \
&& ant preppkg-linux-only \
&& rm -rf pkg-temp/osid pkg-temp/lib/wrapper pkg-temp/lib/wrapper.* \
&& apk del build-base gettext tar bzip2 apache-ant openjdk17
&& del-pkg build-base gettext tar bzip2 apache-ant openjdk8
FROM alpine:3.17.1
FROM jlesage/baseimage:alpine-3.15-glibc
ENV APP_HOME="/i2p"
RUN apk add openjdk17-jre ttf-dejavu
RUN add-pkg openjdk8-jre
WORKDIR ${APP_HOME}
COPY --from=builder /tmp/build/pkg-temp .
# "install" i2p by copying over installed files
COPY --chown=root:root docker/rootfs/ /
RUN chmod +x /startapp.sh
COPY docker/rootfs/ /
# Mount home and snark
VOLUME ["${APP_HOME}/.i2p"]
@ -37,4 +34,3 @@ LABEL \
org.label-schema.vcs-url="https://github.com/i2p/i2p.i2p" \
org.label-schema.schema-version="1.0"
ENTRYPOINT ["/startapp.sh"]

View File

@ -267,7 +267,7 @@ Applications:
See licenses/LICENSE-Apache2.0.txt
See licenses/LICENSE-ECLIPSE-1.0.html
RRD4J 3.10 (jrobin.jar):
RRD4J 3.8 (jrobin.jar):
Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
Copyright (c) 2011 The OpenNMS Group, Inc.
Copyright 2011 The RRD4J Authors.
@ -316,10 +316,6 @@ Applications:
See licenses/LICENSE-NDT.txt
Notice: I2P has changed specified portions of the Software, including the package edu.internet2.ndt.
Router Console Iframe-resizer 4.3.9:
Copyright (c) 2013-2023 David J. Bradshaw
See licenses/LICENSE-Iframe-resizer.txt
SAM (sam.jar):
Public domain.
@ -336,19 +332,12 @@ Applications:
GPLv2 (or any later version)
See licenses/LICENSE-GPLv2.txt
SusiMail Pagedown:
Original Markdown Copyright (c) 2004-2005 John Gruber
Original Showdown code copyright (c) 2007 John Fraser
Modifications and bugfixes (c) 2009 Dana Robinson
Modifications and bugfixes (c) 2009-2014 Stack Exchange Inc.
See licenses/LICENSE-pagedown.txt
Systray (systray.jar):
Public domain.
Tomcat 9.0.88 (jasper-runtime.jar):
Tomcat 9.0.62 (jasper-runtime.jar):
(not included in most distribution packages)
Copyright 1999-2024 The Apache Software Foundation
Copyright 1999-2022 The Apache Software Foundation
See licenses/LICENSE-Apache2.0.txt
See licenses/NOTICE-Tomcat.txt
@ -362,7 +351,7 @@ distributions. See the source package for the additional license information.
Admin Manager:
Public domain
Gradle wrapper 8.5:
Gradle wrapper 5.2.1:
(not included in most distribution packages)
Copyright (c) 2023 the original author or authors.
Copyright (c) 2017 the original author or authors.
See licenses/LICENSE-Apache2.0.txt

View File

@ -9,7 +9,6 @@
<property name="javac.compilerargs" value="" />
<property name="javac.version" value="1.8" />
<property name="javac.release" value="8" />
<property name="manifest.classpath.name" value="Class-Path" />
<target name="all" depends="jar, emptyWar"/>
@ -58,14 +57,8 @@
<property name="workspace.changes.tr" value="" />
<jar basedir="${build}" destfile="${dist}/${jar}">
<manifest>
<attribute name="${manifest.classpath.name}" value="i2p.jar" />
<attribute name="Main-Class" value="net.i2p.addressbook.CommandLine"/>
<attribute name="Specification-Title" value="I2P Address Book" />
<attribute name="Specification-Version" value="${api.version}" />
<attribute name="Specification-Vendor" value="The I2P Project https://geti2p.net/" />
<attribute name="Implementation-Title" value="I2P Java Address Book" />
<attribute name="Main-Class" value="net.i2p.addressbook.Daemon"/>
<attribute name="Implementation-Version" value="${full.version}" />
<attribute name="Implementation-Vendor" value="The I2P Project https://geti2p.net/" />
<attribute name="Built-By" value="${build.built-by}" />
<attribute name="Build-Date" value="${build.timestamp}" />
<attribute name="Base-Revision" value="${workspace.version}" />
@ -84,36 +77,28 @@
</jar>
</target>
<!-- actually the jar -->
<target name="warUpToDate">
<uptodate property="war.uptodate" targetfile="${dist}/${jar}">
<srcfiles dir= "." includes="${build}/**/*.class"/>
<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="git.available" />
<isset property="mtn.available" />
</and>
</condition>
</target>
<target name="changes" depends="warUpToDate" if="shouldListChanges" >
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value="." />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
<arg value="." />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<exec executable="tr" inputstring="${workspace.changes}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />

View File

@ -136,17 +136,9 @@ class AddressBook implements Iterable<Map.Entry<String, HostTxtEntry>> {
File tmp = null;
try {
tmp = SecureFile.createTempFile("addressbook", null, I2PAppContext.getGlobalContext().getTempDir());
// Apache 2.4 mod_deflate etag bug workaround
// strip -gzip from the etag
// Gitlab #454
String loc = subscription.getLocation();
String etag = subscription.getEtag();
if (loc.startsWith("http://i2p-projekt.i2p/") && etag != null && etag.endsWith("-gzip\""))
etag = etag.substring(0, etag.length() - 6) + '"';
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
proxyHost, proxyPort, 0, -1l, MAX_SUB_SIZE, tmp.getAbsolutePath(), null,
loc, true, etag, subscription.getLastModified(), null);
subscription.getLocation(), true, subscription.getEtag(), subscription.getLastModified(), null);
if (get.fetch()) {
subscription.setEtag(get.getETag());
subscription.setLastModified(get.getLastModified());

View File

@ -1,42 +0,0 @@
package net.i2p.addressbook;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.i2p.CoreVersion;
/**
* Simple command line access to various utilities.
* Not a public API. Subject to change.
* Apps and plugins should use specific classes.
*
* @since 0.9.55
*/
public class CommandLine extends net.i2p.util.CommandLine {
protected static final List<String> ACLASSES = Arrays.asList(new String[] {
"net.i2p.addressbook.HostTxtParser",
"net.i2p.router.naming.BlockfileNamingService",
"net.metanotion.io.block.BlockFile",
});
protected CommandLine() {}
public static void main(String args[]) {
List<String> classes = new ArrayList<String>(ACLASSES.size() + CLASSES.size());
classes.addAll(ACLASSES);
classes.addAll(CLASSES);
if (args.length > 0) {
exec(args, classes);
}
usage(classes);
System.exit(1);
}
private static void usage(List<String> classes) {
System.err.println("I2P Address book version " + CoreVersion.VERSION + '\n' +
"USAGE: java -jar /path/to/addressbook.jar command [args]");
printCommands(classes);
}
}

View File

@ -697,7 +697,7 @@ class Daemon {
StringBuilder buf = new StringBuilder(16);
final int sz = dests.size();
for (int i = 0; i < sz; i++) {
buf.append(dests.get(i).toBase64(), 0, 6);
buf.append(dests.get(i).toBase64().substring(0, 6));
if (i != sz - 1)
buf.append(", ");
}

View File

@ -17,7 +17,6 @@ import java.util.Properties;
import net.i2p.client.naming.HostTxtEntry;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.SecureFile;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SystemVersion;
@ -26,9 +25,9 @@ import net.i2p.util.SystemVersion;
* Utility class providing methods to parse and write files in a hosts.txt file
* format, and subscription file format.
*
* @since 0.9.26 modified from ConfigParser, public since 0.9.55 for CLI
* @since 0.9.26 modified from ConfigParser
*/
public class HostTxtParser {
class HostTxtParser {
private static final boolean isWindows = SystemVersion.isWindows();
@ -256,23 +255,8 @@ public class HostTxtParser {
System.exit(2);
}
if (!e.hasValidSig()) {
if (!quiet) {
System.err.println("Bad signature for " + e.getName());
String dest = e.getDest();
try {
Destination d = new Destination(dest);
System.err.println(dest);
System.err.println(d.toString());
} catch (Exception ex) {
System.err.println("Invalid destination: " + dest);
}
Properties p = e.getProps();
if (p != null) {
for (Map.Entry<?,?> m : p.entrySet()) {
System.err.println(m.getKey() + "=" + m.getValue());
}
}
}
if (!quiet)
System.err.println("Bad signature");
System.exit(3);
}
Properties p = e.getProps();
@ -282,30 +266,14 @@ public class HostTxtParser {
p.containsKey(HostTxtEntry.PROP_OLDNAME) ||
p.containsKey(HostTxtEntry.PROP_OLDSIG)) {
if (!e.hasValidSig()) {
if (!quiet) {
System.err.println("Bad inner signature for " + e.getName());
for (Map.Entry<?,?> m : p.entrySet()) {
System.err.println(m.getKey() + "=" + m.getValue());
}
}
if (!quiet)
System.err.println("Bad inner signature");
System.exit(4);
}
}
}
if (!quiet) {
if (!quiet)
System.err.println("Good signature for " + e.getName());
try {
String dest = e.getDest();
Destination d = new Destination(dest);
System.err.println(dest);
System.err.println(d.toString());
} catch (Exception ex) {}
if (p != null) {
for (Map.Entry<?,?> m : p.entrySet()) {
System.err.println(m.getKey() + "=" + m.getValue());
}
}
}
System.exit(0);
}

View File

@ -23,14 +23,11 @@ package net.i2p.addressbook;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Date;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.SecureFileOutputStream;
/**
* A simple log with automatic time stamping.
*
@ -60,9 +57,9 @@ class Log {
public void append(String entry) {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(this.file,
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.file,
true), "UTF-8"));
String timestamp = DataHelper.formatTime(I2PAppContext.getGlobalContext().clock().now());
String timestamp = new Date().toString();
bw.write(timestamp + " -- " + entry);
bw.newLine();
} catch (IOException exp) {

View File

@ -762,10 +762,6 @@ public class BlockfileNamingService extends DummyNamingService {
*/
@Override
public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
if (hostname.endsWith(".i2p.alt")) {
// RFC 9476
hostname = hostname.substring(0, hostname.length() - 4);
}
Destination rv = lookup2(hostname, lookupOptions, storedOptions);
if (rv == null) {
// if hostname starts with "www.", strip and try again
@ -1435,8 +1431,6 @@ public class BlockfileNamingService extends DummyNamingService {
}
/**
* Broken prior to 0.9.62, would only return one name.
*
* @param options If non-null and contains the key "list", get
* from that list (default "hosts.txt", NOT all lists)
* Key "skip": skip that many entries
@ -1508,7 +1502,6 @@ public class BlockfileNamingService extends DummyNamingService {
break;
}
}
iter.next();
if (search != null && key.indexOf(search) < 0)
continue;
rv.add(key);

View File

@ -1,8 +0,0 @@
<html>
<body>
<p>
The BlockfileNamingService based on the Metanotion BlockFile Database.
This is the default NamingService for the router.
</p>
</body>
</html>

View File

@ -1,7 +1,3 @@
plugins {
id 'java-library'
}
sourceSets {
main {
java {
@ -12,10 +8,10 @@ sourceSets {
}
dependencies {
api project(':core')
api project(':router')
api project(':installer')
api project(':apps:systray')
compile project(':core')
compile project(':router')
compile project(':installer')
compile project(':apps:systray')
}
// Create the java files from the po files. The jar task will compile them.

View File

@ -64,24 +64,17 @@
</target>
<target name="listChangedFiles" depends="jarUpToDate" if="shouldListChanges" >
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value="." />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
</exec>
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
<arg value="." />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<target name="jar" depends="compile, bundle, listChangedFiles" unless="jar.uptodate" >
@ -115,7 +108,7 @@
<not>
<isset property="jar.uptodate" />
</not>
<isset property="git.available" />
<isset property="mtn.available" />
</and>
</condition>
</target>

View File

@ -7,15 +7,14 @@
# blabla <blabla@trash-mail.com>, 2011
# Ettore Atalan <atalanttore@googlemail.com>, 2016
# foo <foo@bar>, 2009
# Georg Stadler, 2022
# Lars Schimmer <echelon@i2pmail.org>, 2016
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Georg Stadler, 2022\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: Lars Schimmer <echelon@i2pmail.org>\n"
"Language-Team: German (http://www.transifex.com/otf/I2P/language/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -30,81 +29,69 @@ msgstr "I2P starten"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P startet gerade!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Startend"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "I2P-Browser öffnen"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "I2P System Tray konfigurieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Benachrichtigungen aktivieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Deaktivieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Benachrichtigungen deaktivieren"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "I2P neustarten"
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "I2P beenden"
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "I2P sofort neustarten"
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "I2P sofort beenden"
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Herunterfahren von I2P abbrechen"
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Herunterfahren in {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Herunterfahren bevorstehend"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Netzwerk"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:73
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: Rechtsklick für Menü"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P desktopgui\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"POT-Creation-Date: 2022-02-09 19:13+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"
@ -19,84 +19,87 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr ""
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr ""
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr ""
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr ""
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr ""
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:75
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr ""
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr ""
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr ""

View File

@ -6,22 +6,21 @@
# Translators:
# ducki2p <ducki2p@gmail.com>, 2011
# foo <foo@bar>, 2009
# Juan Jaramillo <juanda097@protonmail.ch>, 2022
# punkibastardo <transifex.symons@slmail.me>, 2011
# punkibastardo <punkibastardo@gmail.com>, 2011
# strel, 2016
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Juan Jaramillo <juanda097@protonmail.ch>, 2022\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: strel\n"
"Language-Team: Spanish (http://www.transifex.com/otf/I2P/language/es/)\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=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
@ -30,81 +29,69 @@ msgstr "Iniciar I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P está iniciando!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Iniciando"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Lanzar navegador I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Configurar la bandeja de sistema de I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Activar las notificaciones"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Deshabilitar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Desactivar las notificaciones"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Desactivar la bandeja del sistema"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Reiniciar I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Detener I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Reiniciar I2P inmediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Detener I2P inmediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Cancelar el cierre de I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Cierre en {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Cierre inminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Red"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:73
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: Clic secundario para menú"

View File

@ -9,15 +9,15 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: kaze kaze <kaze@rlab.be>, 2017\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-11-16 15:29+0000\n"
"Last-Translator: kaze kaze <kaze@rlab.be>\n"
"Language-Team: Spanish (Argentina) (http://www.transifex.com/otf/I2P/language/es_AR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es_AR\n"
"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
@ -26,81 +26,69 @@ msgstr "Iniciando I2P..."
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P esta iniciando!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Iniciando"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Lanzar el Navegador I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Configurar la Bandeja de Sistema de I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Activar las notificaciones"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Deshabilitar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Desactivar las notificaciones"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Desactivar la bandeja del sistema"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Riniciar I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Detener I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr " Reiniciar I2P inmediatamente "
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr " Detener I2P inmediatamente "
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Cancelar el Apagado de I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Apagar en {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Apagado inminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Red"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:73
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P Clic derecho para el menú"

View File

@ -13,20 +13,19 @@
# AO <ao@localizationlab.org>, 2017
# Boxoa590, 2013
# Towinet, 2016
# vex vex, 2022
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: vex vex, 2022\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2019-12-03 16:10+0000\n"
"Last-Translator: AO <ao@localizationlab.org>\n"
"Language-Team: French (http://www.transifex.com/otf/I2P/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fr\n"
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
@ -35,81 +34,69 @@ msgstr "Démarrer I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P démarre!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Démarrage"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Lancer le navigateur dI2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Configurer la zone de notification dI2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Activer les notifications"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Désactiver"
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Désactiver les notifications"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Désactiver la zone de notification"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Redémarrer I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Arrêter I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Redémarrer I2P immédiatement"
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Arrêter I2P immédiatement"
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Annuler la fermeture dI2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Fermeture dans {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "La fermeture est imminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Réseau"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:73
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P : clic droit pour obtenir le menu"

View File

@ -5,14 +5,13 @@
#
# Translators:
# Hunor Paksy <heds@cock.li>, 2018
# vargaviktor <viktor.varga@gmail.com>, 2022
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: vargaviktor <viktor.varga@gmail.com>, 2022\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2021-06-20 09:44+0000\n"
"Last-Translator: AdminLMH <lehetmashogy@i2pmail.org>\n"
"Language-Team: Hungarian (http://www.transifex.com/otf/I2P/language/hu/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -27,81 +26,69 @@ msgstr "I2P indítása"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P indul!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "indítás"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "I2P Böngésző Indítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "I2P rendszertálca beállítások"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Értesítések engedélyezése"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Kikapcsol"
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Értesítések tiltása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Tálcaikon letiltása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "I2P Újraindítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "I2P Leállítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "I2P Azonnali újraindítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "I2P Azonnali megállítása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "I2P leállításának visszavonása"
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Kikapcsolás: {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Kikapcsolás hamarosan"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Hálózat"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:73
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: Jobb-klikk a menüért"

View File

@ -4,17 +4,16 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Adrian Achyar, 2024
# Khairul Agasta <khairuldroids@gmail.com>, 2014
# Robert Dafis <robertdafis@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Adrian Achyar, 2024\n"
"Language-Team: Indonesian (http://app.transifex.com/otf/I2P/language/id/)\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-07-27 00:14+0000\n"
"Last-Translator: Robert Dafis <robertdafis@gmail.com>\n"
"Language-Team: Indonesian (http://www.transifex.com/otf/I2P/language/id/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -22,84 +21,75 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Mulai I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "I2P is starting!"
msgstr "I2P sudah memulai!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "Starting"
msgstr "Memulai"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Luncurkan Peramban I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Ubah pengaturan I2P System Tray"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Nonaktifkan system tray"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Matikan"
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Mulai ulang I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Hentikan I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Ulang kembali I2P sekarang"
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Hentikan I2P sekarang"
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Batal tutup I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Mematikan I2P dalam {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "I2P sedang dalam proses dimatikan"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Jaringan"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:75
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: klik kanan untuk menampilkan menu"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Aktifkan notifikasi"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Nonaktifkan notifikasi"

View File

@ -8,101 +8,91 @@
# mkkid <jokjok@hotmail.it>, 2011
# Leelium <bovas85@gmail.com>, 2012
# mkkid <jokjok@hotmail.it>, 2011
# SebastianoPistore <SebastianoPistore.info@protonmail.ch>, 2016-2017
# V 41bis, 2023
# Sebastiano Pistore <SebastianoPistore.info@protonmail.ch>, 2016-2017
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: V 41bis, 2023\n"
"Language-Team: Italian (http://app.transifex.com/otf/I2P/language/it/)\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-07-30 07:04+0000\n"
"Last-Translator: Sebastiano Pistore <SebastianoPistore.info@protonmail.ch>\n"
"Language-Team: Italian (http://www.transifex.com/otf/I2P/language/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=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Avvia I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "I2P is starting!"
msgstr "Avvio di I2P in corso!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "Starting"
msgstr "Avvio in corso"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Lancia il browser I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Configura icona di I2P nella Barra di notifica"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Disattiva l'icona nella barra di Notifica"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Disabilita"
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Riavvia I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Arresta I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Riavvia subito I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Arresta subito I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Annulla arresto di I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Arresto in {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Arresto imminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Rete"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:75
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: Fai click destro per aprire il menu"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Attiva le notifiche"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Disattiva le notifiche"

View File

@ -6,15 +6,14 @@
# Translators:
# Allan Nordhøy <epost@anotheragency.no>, 2014
# Allan Nordhøy <epost@anotheragency.no>, 2017
# Imre Kristoffer Eilertsen <imreeil42@gmail.com>, 2022-2023
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Imre Kristoffer Eilertsen <imreeil42@gmail.com>, 2022-2023\n"
"Language-Team: Norwegian Bokmål (http://app.transifex.com/otf/I2P/language/nb/)\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-09-19 14:52+0000\n"
"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
"Language-Team: Norwegian Bokmål (http://www.transifex.com/otf/I2P/language/nb/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -22,84 +21,75 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Start I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "I2P is starting!"
msgstr "I2P starter opp!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "Starting"
msgstr "Starter opp"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Kjør I2P-nettleser"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Sett opp I2P-systemkurv"
msgstr "Sett opp I2P-systemkruv"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Skru av systemkurven"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Skru av"
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Omstart av I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Stopp I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Umiddelbar omstart av I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Umiddelbar stopp av I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Avbryt nedstenging av I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Skrur av om {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Skru av med en gang"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Nettverk"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:75
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "Høyreklikk-meny i I2P"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Skru på varsler"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Skru av varsler"

View File

@ -6,15 +6,14 @@
# Translators:
# PolishAnon <b790979@klzlk.com>, 2011
# polacco <polacco@i2pmail.org>, 2015
# Verdulo, 2016
# Waldemar Napora, 2022
# Verdulo :-), 2016
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Waldemar Napora, 2022\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: Verdulo :-)\n"
"Language-Team: Polish (http://www.transifex.com/otf/I2P/language/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -29,81 +28,69 @@ msgstr "Uruchom I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "Uruchamianie I2P!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Uruchamianie"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Uruchom przeglądarkę I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Konfiguruj I2P w zasobniku systemowym"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "Włącz powiadomenia"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Wyłącz"
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "Wyłącz powiadomienia"
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "Wyłącz zasobnik systemowy"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Zrestartuj I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Zatrzymaj I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Zrestartuj I2P natychmiast"
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Wyłącz I2P natychmiast"
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Anuluj zamykanie I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Wyłączenie za {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Zaraz zamknę"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Sieć"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:73
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: kliknij prawym aby otworzyć menu"

View File

@ -4,102 +4,93 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Manuela Silva <mmsrs@sky.com>, 2016
# 1c13465e24d91aca4d3ddaa1bc3e7027_ae6ba28, 2013
# 1c13465e24d91aca4d3ddaa1bc3e7027_ae6ba28, 2012
# Manuela Silva <manuela.silva@sky.com>, 2016
# wicked, 2013
# wicked, 2012
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Manuela Silva <mmsrs@sky.com>, 2016\n"
"Language-Team: Portuguese (http://app.transifex.com/otf/I2P/language/pt/)\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: Manuela Silva <manuela.silva@sky.com>\n"
"Language-Team: Portuguese (http://www.transifex.com/otf/I2P/language/pt/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt\n"
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Iniciar I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "I2P is starting!"
msgstr "I2P está a iniciar!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "Starting"
msgstr "A Iniciar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Iniciar o browser I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Configurar Bandeja do Sistema do I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Desativar bandeja do sistema"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Desativar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Reiniciar o I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Parar o I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Reiniciar o I2P imediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Parar o I2P de imediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Cancelar Encerramento do I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Encerramento em {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Encerramento eminente"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Rede"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:75
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: Clique direito para menu"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Ativar notificações"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Desativar notificações"

View File

@ -4,105 +4,94 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers
#
# Translators:
# Cauan Henrique Zorzenon <cauanzorzenon@gmail.com>, 2023
# testsubject67 <deborinha97@hotmail.com>, 2014
# ce4434973f224b33f2ea48f4556be467_f116f03, 2022
# L., 2013
# L., 2015
# blueboy, 2013
# blueboy, 2015
# Rafael Ferrari, 2016
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Cauan Henrique Zorzenon <cauanzorzenon@gmail.com>, 2023\n"
"Language-Team: Portuguese (Brazil) (http://app.transifex.com/otf/I2P/language/pt_BR/)\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: Rafael Ferrari\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/otf/I2P/language/pt_BR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt_BR\n"
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Iniciar I2P"
msgstr "Conectar-se à I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "I2P is starting!"
msgstr "Conectando-se a I2P!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "Starting"
msgstr "Conectando"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Lançar o navegador I2P "
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Configurar o ícone de sistema I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Desativar bandeja do sistema"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Desabilitar"
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Reinicializar o roteador I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Interromper o roteador I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Reinicializar o I2P Imediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Parar o I2P Imediatamente"
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Cancelar o desligamento do I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Desligando em {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Desligando agora"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Rede"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:75
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: Clique com o botão direito para o menu"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Ativar notificações"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Desativar notificações"

View File

@ -9,15 +9,14 @@
# foo <foo@bar>, 2009
# Foster Snowhill, 2013
# brianhopes <voganc-12@live.ru>, 2015
# Артём Котлубай <artemkotlubai@yandex.ru>, 2023
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Артём Котлубай <artemkotlubai@yandex.ru>, 2023\n"
"Language-Team: Russian (Russia) (http://app.transifex.com/otf/I2P/language/ru_RU/)\n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: c4sp3r\n"
"Language-Team: Russian (Russia) (http://www.transifex.com/otf/I2P/language/ru_RU/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -25,84 +24,75 @@ msgstr ""
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Запустить I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "I2P is starting!"
msgstr "I2P запускается!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
msgid "Starting"
msgstr "Запускается"
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
msgid "Launch I2P Browser"
msgstr "Запустить браузер I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
msgid "Configure I2P System Tray"
msgstr "Настроить область уведомлений"
msgstr "Настроить системный трей I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Убрать значок из области уведомлений"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Отключить"
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
msgid "Restart I2P"
msgstr "Перезапустить I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
msgid "Stop I2P"
msgstr "Остановить I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
msgid "Restart I2P Immediately"
msgstr "Перезапустить I2P немедленно"
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
msgid "Stop I2P Immediately"
msgstr "Остановить I2P немедленно"
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
msgid "Cancel I2P Shutdown"
msgstr "Отменить выключение I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#, java-format
msgid "Shutdown in {0}"
msgstr "Выключение через {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Shutdown imminent"
msgstr "Неотменяемое выключение"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
msgid "Network"
msgstr "Сеть"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:75
#: src/net/i2p/desktopgui/TrayManager.java:63
msgid "I2P: Right-click for menu"
msgstr "I2P: ПКМ для вызова меню"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Включить уведомления"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Отключить уведомления"
msgstr "I2P: Правый щелчок для вызова меню"

View File

@ -13,9 +13,6 @@ import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientApp;
import net.i2p.app.ClientAppState;
import net.i2p.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.app.MenuService;
import net.i2p.app.NotificationService;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
@ -27,7 +24,7 @@ import net.i2p.util.SystemVersion;
*
* @since 0.9.54
*/
public class ExternalMain implements ClientApp, NotificationService, MenuService {
public class ExternalMain implements ClientApp, NotificationService {
private final I2PAppContext _appContext;
private final ClientAppManager _mgr;
@ -63,6 +60,7 @@ public class ExternalMain implements ClientApp, NotificationService, MenuService
* @throws AWTException on startup error, including systray not supported
*/
private synchronized void startUp() throws Exception {
final TrayManager trayManager;
boolean useSwingDefault = !(SystemVersion.isWindows() || SystemVersion.isMac());
boolean useSwing = _appContext.getProperty(PROP_SWING, useSwingDefault);
_trayManager = new ExternalTrayManager(_appContext, useSwing);
@ -202,89 +200,6 @@ public class ExternalMain implements ClientApp, NotificationService, MenuService
return false;
}
/////// MenuService methods
/**
* Menu will start out shown and enabled, in the root menu
*
* @param message for the menu, translated
* @param callback fired on click
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback) {
return addMenu(message, callback, null);
}
/**
* Menu will start out enabled, as a submenu
*
* @param message for the menu, translated
* @param callback fired on click
* @param parent the parent menu this will be a submenu of, or null for top level
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback, MenuHandle parent) {
if (_trayManager == null)
return null;
return _trayManager.addMenu(message, callback, parent);
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.removeMenu(item);
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.showMenu(item);
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.hideMenu(item);
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.enableMenu(item);
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.disableMenu(item);
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.updateMenu(message, item);
}
/////// ClientApp methods
public synchronized void startup() {

View File

@ -51,15 +51,11 @@ class ExternalTrayManager extends TrayManager {
}
});
popup.add(startItem);
initializeNotificationItems();
popup.add(_notificationItem2);
popup.add(_notificationItem1);
return popup;
}
public JPopupMenu getSwingMainMenu() {
JPopupMenu popup = new JPopupMenu();
/*
JMenuItem startItem = new JMenuItem(_t("Start I2P"));
startItem.addActionListener(new ActionListener() {
@Override
@ -83,10 +79,6 @@ class ExternalTrayManager extends TrayManager {
}
});
popup.add(startItem);
*/
initializeJNotificationItems();
popup.add(_jnotificationItem2);
popup.add(_jnotificationItem1);
return popup;
}
@ -94,14 +86,5 @@ class ExternalTrayManager extends TrayManager {
* Update the menu
* @since 0.9.26
*/
protected void updateMenu() {
if (_notificationItem1 != null)
_notificationItem1.setEnabled(_showNotifications);
if (_notificationItem2 != null)
_notificationItem2.setEnabled(!_showNotifications);
if (_jnotificationItem1 != null)
_jnotificationItem1.setVisible(_showNotifications);
if (_jnotificationItem2 != null)
_jnotificationItem2.setVisible(!_showNotifications);
}
protected void updateMenu() {}
}

View File

@ -32,9 +32,11 @@ class InternalTrayManager extends TrayManager {
private final Log log;
private final Main _main;
private MenuItem _statusItem, _browserItem, _configItem, _restartItem, _stopItem,
_restartHardItem, _stopHardItem, _cancelItem;
_restartHardItem, _stopHardItem, _cancelItem,
_notificationItem1, _notificationItem2;
private JMenuItem _jstatusItem, _jbrowserItem, _jconfigItem, _jrestartItem, _jstopItem,
_jrestartHardItem, _jstopHardItem, _jcancelItem;
_jrestartHardItem, _jstopHardItem, _jcancelItem,
_jnotificationItem1, _jnotificationItem2;
private static final boolean CONSOLE_ENABLED = Desktop.isDesktopSupported() &&
Desktop.getDesktop().isSupported(Action.BROWSE);
@ -84,6 +86,33 @@ class InternalTrayManager extends TrayManager {
}
PopupMenu desktopguiConfigurationLauncher = new PopupMenu(_t("Configure I2P System Tray"));
final MenuItem notificationItem2 = new MenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
final MenuItem notificationItem1 = new MenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
MenuItem configSubmenu = new MenuItem(_t("Disable system tray"));
configSubmenu.addActionListener(new ActionListener() {
@ -185,9 +214,8 @@ class InternalTrayManager extends TrayManager {
popup.add(browserLauncher);
popup.addSeparator();
}
initializeNotificationItems();
desktopguiConfigurationLauncher.add(_notificationItem2);
desktopguiConfigurationLauncher.add(_notificationItem1);
desktopguiConfigurationLauncher.add(notificationItem2);
desktopguiConfigurationLauncher.add(notificationItem1);
desktopguiConfigurationLauncher.add(configSubmenu);
popup.add(desktopguiConfigurationLauncher);
popup.addSeparator();
@ -202,6 +230,8 @@ class InternalTrayManager extends TrayManager {
_statusItem = statusItem;
_browserItem = browserLauncher;
_configItem = desktopguiConfigurationLauncher;
_notificationItem1 = notificationItem1;
_notificationItem2 = notificationItem2;
_restartItem = restartItem;
_stopItem = stopItem;
_restartHardItem = restartItem2;
@ -240,6 +270,33 @@ class InternalTrayManager extends TrayManager {
}
JMenu desktopguiConfigurationLauncher = new JMenu(_t("Configure I2P System Tray"));
final JMenuItem notificationItem2 = new JMenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
final JMenuItem notificationItem1 = new JMenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
JMenuItem configSubmenu = new JMenuItem(_t("Disable system tray"));
configSubmenu.addActionListener(new ActionListener() {
@ -341,9 +398,8 @@ class InternalTrayManager extends TrayManager {
popup.add(browserLauncher);
popup.addSeparator();
}
initializeJNotificationItems();
desktopguiConfigurationLauncher.add(_jnotificationItem2);
desktopguiConfigurationLauncher.add(_jnotificationItem1);
desktopguiConfigurationLauncher.add(notificationItem2);
desktopguiConfigurationLauncher.add(notificationItem1);
desktopguiConfigurationLauncher.add(configSubmenu);
popup.add(desktopguiConfigurationLauncher);
popup.addSeparator();
@ -358,6 +414,8 @@ class InternalTrayManager extends TrayManager {
_jstatusItem = statusItem;
_jbrowserItem = browserLauncher;
_jconfigItem = desktopguiConfigurationLauncher;
_jnotificationItem1 = notificationItem1;
_jnotificationItem2 = notificationItem2;
_jrestartItem = restartItem;
_jstopItem = stopItem;
_jrestartHardItem = restartItem2;
@ -453,8 +511,7 @@ class InternalTrayManager extends TrayManager {
/**
* @since 0.9.53
*/
@Override
protected void configureNotifications(boolean enable) {
private void configureNotifications(boolean enable) {
_showNotifications = enable;
String value = Boolean.toString(enable);
if (!_context.router().saveConfig(PROP_NOTIFICATIONS, value))

View File

@ -17,9 +17,6 @@ import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import static net.i2p.app.ClientAppState.*;
import net.i2p.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.app.MenuService;
import net.i2p.app.NotificationService;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.router.RouterContext;
@ -32,7 +29,7 @@ import net.i2p.util.I2PProperties.I2PPropertyCallback;
/**
* The main class of the application.
*/
public class Main implements RouterApp, NotificationService, MenuService {
public class Main implements RouterApp, NotificationService {
// non-null
private final I2PAppContext _appContext;
@ -248,89 +245,6 @@ public class Main implements RouterApp, NotificationService, MenuService {
return false;
}
/////// MenuService methods
/**
* Menu will start out shown and enabled, in the root menu
*
* @param message for the menu, translated
* @param callback fired on click
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback) {
return addMenu(message, callback, null);
}
/**
* Menu will start out enabled, as a submenu
*
* @param message for the menu, translated
* @param callback fired on click
* @param parent the parent menu this will be a submenu of, or null for top level
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback, MenuHandle parent) {
if (_trayManager == null)
return null;
return _trayManager.addMenu(message, callback, parent);
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.removeMenu(item);
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.showMenu(item);
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.hideMenu(item);
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.enableMenu(item);
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.disableMenu(item);
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.updateMenu(message, item);
}
/////// ClientApp methods
/** @since 0.9.26 */

View File

@ -4,7 +4,6 @@ import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
@ -17,12 +16,8 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingWorker;
import javax.swing.event.MenuKeyEvent;
@ -31,8 +26,6 @@ import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import net.i2p.I2PAppContext;
import net.i2p.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.apps.systray.UrlLauncher;
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
import net.i2p.util.Log;
@ -50,11 +43,6 @@ abstract class TrayManager {
///Our tray icon, or null if unsupported
protected TrayIcon trayIcon;
protected volatile boolean _showNotifications;
protected MenuItem _notificationItem1, _notificationItem2;
protected JMenuItem _jnotificationItem1, _jnotificationItem2;
private final AtomicInteger _id = new AtomicInteger();
private final List<MenuInternal> _menus;
private JPopupMenu _jPopupMenu;
private static final String PNG_DIR = "/desktopgui/resources/images/";
private static final String MAC_ICON = "itoopie_black_24.png";
@ -69,7 +57,6 @@ abstract class TrayManager {
protected TrayManager(I2PAppContext ctx, boolean useSwing) {
_appContext = ctx;
_useSwing = useSwing;
_menus = new ArrayList<MenuInternal>();
}
/**
@ -118,7 +105,6 @@ abstract class TrayManager {
frame.setMinimumSize(new Dimension(0, 0));
frame.setSize(0, 0);
final JPopupMenu menu = getSwingMainMenu();
_jPopupMenu = menu;
menu.setFocusable(true);
frame.add(menu);
TrayIcon ti = new TrayIcon(getTrayImage(), tooltip, null);
@ -302,248 +288,6 @@ abstract class TrayManager {
return 0;
}
/**
* Does not save. See InternalTrayManager.
*
* @since 0.9.58 moved up from InternalTrayManager
*/
protected void configureNotifications(boolean enable) {
_showNotifications = enable;
}
/**
* Initializes _notificationItem 1 and 2
*
* @since 0.9.58 pulled out of InternalTrayManager
*/
protected void initializeNotificationItems() {
final MenuItem notificationItem2 = new MenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
_notificationItem2 = notificationItem2;
final MenuItem notificationItem1 = new MenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
_notificationItem1 = notificationItem1;
}
/**
* Initializes _jnotificationItem 1 and 2
*
* @since 0.9.58 pulled out of InternalTrayManager
*/
protected void initializeJNotificationItems() {
final JMenuItem notificationItem2 = new JMenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
_jnotificationItem2 = notificationItem2;
final JMenuItem notificationItem1 = new JMenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
_jnotificationItem1 = notificationItem1;
}
/////// MenuService delegation methods
/**
* @since 0.9.59
*/
public MenuHandle addMenu(String message, final MenuCallback callback, MenuHandle p) {
MenuInternal parent = p != null ? (MenuInternal) p : null;
final int id = _id.incrementAndGet();
final MenuInternal rv;
if (_useSwing) {
final JMenuItem m = new JMenuItem(message);
rv = new MenuInternal(null, m, callback, id);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
rv.cb.clicked(rv);
return null;
}
}.execute();
}
});
_jPopupMenu.add(m);
} else {
final MenuItem m = new MenuItem(message);
rv = new MenuInternal(m, null, callback, id);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
rv.cb.clicked(rv);
return null;
}
}.execute();
}
});
trayIcon.getPopupMenu().add(m);
}
synchronized(_menus) {
_menus.add(rv);
}
updateMenu();
return rv;
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
if (_useSwing) {
_jPopupMenu.remove(mi.jm);
} else {
trayIcon.getPopupMenu().remove(mi.m);
}
updateMenu();
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setVisible(true);
updateMenu();
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setVisible(false);
updateMenu();
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setEnabled(true);
updateMenu();
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setEnabled(false);
updateMenu();
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setText(message);
updateMenu();
}
/////// MenuService internals
/**
* @since 0.9.59
*/
private MenuInternal getMenu(int id) {
synchronized(_menus) {
for (MenuInternal mi : _menus) {
if (mi.getID() == id)
return mi;
}
}
return null;
}
/**
* @since 0.9.59
*/
private static class MenuInternal implements MenuHandle {
private final MenuItem m;
private final JMenuItem jm;
private final MenuCallback cb;
private final int id;
public MenuInternal(MenuItem mm, JMenuItem jmm, MenuCallback cbb, int idd) {
m = mm; jm = jmm; cb = cbb; id = idd;
}
public int getID() { return id; }
private void setEnabled(boolean yes) {
if (m != null)
m.setEnabled(yes);
else
jm.setEnabled(yes);
}
private void setVisible(boolean yes) {
if (m != null)
m.setEnabled(yes);
else
jm.setVisible(yes);
}
private void setText(String text) {
if (m != null)
m.setLabel(text);
else
jm.setText(text);
}
}
protected String _t(String s) {
return DesktopguiTranslator._t(_appContext, s);
}

View File

@ -1,5 +1,4 @@
plugins {
id 'java-library'
id 'war'
}
@ -12,15 +11,13 @@ sourceSets {
}
dependencies {
api project(':router')
api project(':apps:jetty')
api files('../../installer/lib/wrapper/all/wrapper.jar')
api fileTree("../jetty/apache-tomcat-${tomcatVersion}")
api fileTree("../jetty/jetty-distribution-${jettyVersion}")
providedCompile project(':router')
providedCompile project(':apps:jetty')
providedCompile files('../../installer/lib/wrapper/all/wrapper.jar')
}
war {
archiveBaseName.set('jsonrpc')
archiveName 'jsonrpc.war'
webXml = file('web.xml')
}

View File

@ -92,29 +92,7 @@
</javac>
</target>
<target name="listChangedFiles" if="git.available" >
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value="." />
<arg value="../resources" />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<target name="jar" depends="compile, listChangedFiles">
<target name="jar" depends="compile">
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar destfile="build/i2pcontrol.jar" basedir="./build/obj" includes="**/*.class" >
@ -130,7 +108,7 @@
</jar>
</target>
<target name="socketJar" depends="compileSocketJar, listChangedFiles">
<target name="socketJar" depends="compileSocketJar">
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar destfile="build/i2pcontrol.jar" basedir="./build/obj" includes="**/*.class" >
@ -146,7 +124,7 @@
</jar>
</target>
<target name="war" depends="compile, listChangedFiles" >
<target name="war" depends="compile" >
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<war destfile="build/jsonrpc.war" webxml="web.xml" >

View File

@ -170,7 +170,7 @@ public class RouterInfoHandler implements RequestHandler {
&& (!_context.router().gracefulShutdownInProgress())
&& !_context.clientManager().isAlive())
return (NETWORK_STATUS.ERROR_I2CP);
long skew = _context.commSystem().getFramedAveragePeerClockSkew(10);
long skew = _context.commSystem().getFramedAveragePeerClockSkew(33);
// Display the actual skew, not the offset
if (Math.abs(skew) > 60 * 1000)
return NETWORK_STATUS.ERROR_CLOCK_SKEW;
@ -200,7 +200,7 @@ public class RouterInfoHandler implements RequestHandler {
case CommSystemFacade.STATUS_IPV4_DISABLED_IPV6_FIREWALLED:
if (_context.router().getRouterInfo().getTargetAddress("NTCP2") != null)
return NETWORK_STATUS.WARN_FIREWALLED_WITH_INBOUND_TCP;
if (_context.netDb().floodfillEnabled())
if (((FloodfillNetworkDatabaseFacade) _context.netDb()).floodfillEnabled())
return NETWORK_STATUS.WARN_FIREWALLED_AND_FLOODFILL;
if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0)
return NETWORK_STATUS.WARN_FIREWALLED_AND_FAST;

View File

@ -1,5 +1,4 @@
plugins {
id 'java-library'
id 'war'
}
@ -13,14 +12,11 @@ sourceSets {
}
dependencies {
api project(':core')
api project(':apps:systray')
api 'gnu.getopt:java-getopt:1.0.13'
api project(':apps:ministreaming')
api project(':apps:jetty')
// this is not needed except for standalone,
// but we build the standalone classes even for non-standalone
api project(':apps:desktopgui')
compile project(':core')
providedCompile project(':apps:systray')
compile 'gnu.getopt:java-getopt:1.0.13'
providedCompile project(':apps:ministreaming')
providedCompile project(':apps:jetty')
}
task i2psnarkJar(type: Jar) {

View File

@ -10,5 +10,3 @@
#routerconsole.browser=firefox
# disable system tray
#desktopgui.enabled=false
# disable system tray notification popups
#desktopgui.showNotifications=false

View File

@ -68,20 +68,13 @@
</target>
<target name="listChangedFiles" depends="jarUpToDate" if="shouldListChanges" >
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
<arg value=".." />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<exec executable="tr" inputstring="${workspace.changes}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
@ -118,7 +111,7 @@
<not>
<isset property="war.uptodate" />
</not>
<isset property="git.available" />
<isset property="mtn.available" />
</and>
</condition>
</target>
@ -259,12 +252,10 @@
<attribute name="Build-Date" value="${build.timestamp}" />
<attribute name="Base-Revision" value="${workspace.version}" />
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
<attribute name="X-Compile-Source-JDK" value="${javac.version}" />
<attribute name="X-Compile-Target-JDK" value="${javac.version}" />
<!-- this is so Jetty will report its version correctly -->
<section name="org/eclipse/jetty/server/" >
<attribute name="Implementation-Vendor" value="Eclipse.org - Jetty" />
<attribute name="Implementation-Version" value="${jetty.ver}" />
<attribute name="Implementation-Version" value="8.1.17.v20150415" />
</section>
</manifest>
</jar>
@ -307,12 +298,6 @@
value="url(/i2psnark/.resources/themes/ubergine/images/" >
<include name="**/*.css" />
</replace>
<replace dir="build/standalone-resources/.resources/themes"
summary="true"
token="url(/themes/console/images/buttons/"
value="url(/i2psnark/.resources/icons/" >
<include name="**/*.css" />
</replace>
<!-- Rather than pulling in all the console theme images, let's just specify the ones we need -->
<copy file="../../routerconsole/jsp/themes/console/images/transparent.gif"
@ -323,8 +308,6 @@
todir="build/standalone-resources/.resources/themes/light/images" />
<copy file="../../routerconsole/jsp/themes/console/images/info/errortriangle.png"
todir="build/standalone-resources/.resources/themes/ubergine/images" />
<copy file="../../routerconsole/jsp/themes/console/images/buttons/search.png"
todir="build/standalone-resources/.resources/icons" />
<mkdir dir="build/standalone-resources/.resources/js" />
<copy file="../../routerconsole/jsp/js/ajax.js" todir="build/standalone-resources/.resources/js" />

View File

@ -6,7 +6,6 @@ package org.klomp.snark;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PSession;
@ -33,9 +32,7 @@ class BWLimits {
session.connect();
rv = session.bandwidthLimits();
session.destroySession();
} catch (I2PSessionException ise) {
I2PAppContext.getGlobalContext().logManager().getLog(BWLimits.class).warn("BWL fail", ise);
}
} catch (I2PSessionException ise) {}
return rv;
}

View File

@ -1,63 +0,0 @@
package org.klomp.snark;
/**
* Bandwidth and bandwidth limits
*
* Maintain three bandwidth estimators:
* Sent, received, and requested.
*
* @since 0.9.62
*/
public interface BandwidthListener {
/**
* The average rate in Bps
*/
public long getUploadRate();
/**
* The average rate in Bps
*/
public long getDownloadRate();
/**
* We unconditionally sent this many bytes
*/
public void uploaded(int size);
/**
* We unconditionally received this many bytes
*/
public void downloaded(int size);
/**
* Should we send this many bytes?
* Do NOT call uploaded() if this returns true.
*/
public boolean shouldSend(int size);
/**
* Should we request this many bytes?
*/
public boolean shouldRequest(Peer peer, int size);
/**
* Current limit in BPS
*/
public long getUpBWLimit();
/**
* Current limit in BPS
*/
public long getDownBWLimit();
/**
* Are we currently over the limit?
*/
public boolean overUpBWLimit();
/**
* Are we currently over the limit?
*/
public boolean overDownBWLimit();
}

View File

@ -1,179 +0,0 @@
package org.klomp.snark;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import net.i2p.util.SyntheticREDQueue;
/**
* Bandwidth and bandwidth limits
*
* Maintain three bandwidth estimators:
* Sent, received, and requested.
*
* There are three layers of BandwidthListeners:
*<pre>
* BandwidthManager (total)
* PeerCoordinator (per-torrent)
* Peer/WebPeer (per-connection)
*</pre>
*
* Here at the top, we use SyntheticRedQueues for accurate
* and current moving averages of up, down, and requested bandwidth.
*
* At the lower layers, simple weighted moving averages of
* three buckets of 40 seconds each (2 minutes total) are used
* for up and down, and requested is delegated here.
*
* The lower layers must report to the next-higher layer.
*
* At the Peer layer, we report inbound piece data per-read,
* not per-piece, to get a smoother inbound estimate.
*
* Only the following data are counted by the BandwidthListeners:
*<ul><li>Pieces (both Peer and WebPeer)
*<li>ut_metadata
*</ul>
*
* No overhead at any layer is accounted for.
*
* @since 0.9.62
*/
public class BandwidthManager implements BandwidthListener {
private final I2PAppContext _context;
private final Log _log;
private SyntheticREDQueue _up, _down, _req;
BandwidthManager(I2PAppContext ctx, int upLimit, int downLimit) {
_context = ctx;
_log = ctx.logManager().getLog(BandwidthManager.class);
_up = new SyntheticREDQueue(ctx, upLimit);
_down = new SyntheticREDQueue(ctx, downLimit);
// Allow down limit a little higher based on testing
// Allow req limit a little higher still because it uses RED
// so it actually kicks in sooner.
_req = new SyntheticREDQueue(ctx, downLimit * 110 / 100);
}
/**
* Current limit in Bps
*/
void setUpBWLimit(long upLimit) {
int limit = (int) Math.min(upLimit, Integer.MAX_VALUE);
if (limit != getUpBWLimit())
_up = new SyntheticREDQueue(_context, limit);
}
/**
* Current limit in Bps
*/
void setDownBWLimit(long downLimit) {
int limit = (int) Math.min(downLimit, Integer.MAX_VALUE);
if (limit != getDownBWLimit()) {
_down = new SyntheticREDQueue(_context, limit);
_req = new SyntheticREDQueue(_context, limit * 110 / 100);
}
}
/**
* The average rate in Bps
*/
long getRequestRate() {
return (long) (1000f * _req.getBandwidthEstimate());
}
// begin BandwidthListener interface
/**
* The average rate in Bps
*/
public long getUploadRate() {
return (long) (1000f * _up.getBandwidthEstimate());
}
/**
* The average rate in Bps
*/
public long getDownloadRate() {
return (long) (1000f * _down.getBandwidthEstimate());
}
/**
* We unconditionally sent this many bytes
*/
public void uploaded(int size) {
_up.addSample(size);
}
/**
* We received this many bytes
*/
public void downloaded(int size) {
_down.addSample(size);
}
/**
* Should we send this many bytes?
* Do NOT call uploaded() if this returns true.
*/
public boolean shouldSend(int size) {
boolean rv = _up.offer(size, 1.0f);
if (!rv && _log.shouldWarn())
_log.warn("Deny sending " + size + " bytes, upload rate " + DataHelper.formatSize(getUploadRate()) + "Bps");
return rv;
}
/**
* Should we request this many bytes?
*
* @param peer ignored
*/
public boolean shouldRequest(Peer peer, int size) {
boolean rv = !overDownBWLimit() && _req.offer(size, 1.0f);
if (!rv && _log.shouldWarn())
_log.warn("Deny requesting " + size + " bytes, download rate " + DataHelper.formatSize(getDownloadRate()) + "Bps" +
", request rate " + DataHelper.formatSize(getRequestRate()) + "Bps");
return rv;
}
/**
* Current limit in BPS
*/
public long getUpBWLimit() {
return _up.getMaxBandwidth();
}
/**
* Current limit in BPS
*/
public long getDownBWLimit() {
return _down.getMaxBandwidth();
}
/**
* Are we currently over the limit?
*/
public boolean overUpBWLimit() {
return getUploadRate() > getUpBWLimit();
}
/**
* Are we currently over the limit?
*/
public boolean overDownBWLimit() {
return getDownloadRate() > getDownBWLimit();
}
/**
* In HTML for debug page
*/
@Override
public String toString() {
return "<br><b>Bandwidth Limiters</b><br><b>Up:</b> " + _up +
"<br><b>Down:</b> " + _down +
"<br><b>Req:</b> " + _req +
"<br>";
}
}

View File

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.i2p.CoreVersion;
/**
* Simple command line access to various utilities.
* Not a public API. Subject to change.
@ -36,7 +38,7 @@ public class CommandLine extends net.i2p.util.CommandLine {
}
private static void usage(List<String> classes) {
System.err.println("I2PSnark version " + SnarkManager.FULL_VERSION + '\n' +
System.err.println("I2PSnark version " + CoreVersion.VERSION + '\n' +
"USAGE: java -jar /path/to/i2psnark.jar command [args]");
printCommands(classes);
}

View File

@ -83,9 +83,4 @@ public interface CompleteListener {
* @since 0.9.42
*/
public boolean shouldAutoStart();
/**
* @since 0.9.62
*/
public BandwidthListener getBandwidthListener();
}

View File

@ -42,5 +42,15 @@ interface CoordinatorListener
*/
public boolean overUploadLimit(int uploaders);
/**
* Is i2psnark as a whole over its limit?
*/
public boolean overUpBWLimit();
/**
* Is a particular peer who has this recent download rate (in Bps) over our upstream bandwidth limit?
*/
public boolean overUpBWLimit(long total);
public void addMessage(String message);
}

View File

@ -190,8 +190,6 @@ abstract class ExtensionHandler {
}
if (log.shouldLog(Log.INFO))
log.info("Request chunk " + chk + " from " + peer);
// ignore the rv, always request
peer.shouldRequest(state.chunkSize(chk));
sendRequest(peer, chk);
}
} catch (Exception e) {
@ -232,6 +230,7 @@ abstract class ExtensionHandler {
sendPiece(peer, piece, pc, totalSize);
// Do this here because PeerConnectionOut only reports for PIECE messages
peer.uploaded(pc.length);
listener.uploaded(peer, pc.length);
} else if (type == TYPE_DATA) {
// On close reading of BEP 9, this is the total metadata size.
// Prior to 0.9.21, we sent the piece size, so we can't count on it.
@ -246,6 +245,7 @@ abstract class ExtensionHandler {
return;
int len = is.available();
peer.downloaded(len);
listener.downloaded(peer, len);
// this checks the size
done = state.saveChunk(piece, bs, bs.length - len, len);
if (log.shouldLog(Log.INFO))
@ -264,8 +264,6 @@ abstract class ExtensionHandler {
// get the next chunk
if (log.shouldLog(Log.INFO))
log.info("Request chunk " + chk + " from " + peer);
// ignore the rv, always request
peer.shouldRequest(state.chunkSize(chk));
sendRequest(peer, chk);
}
} else if (type == TYPE_REJECT) {

View File

@ -1,15 +1,8 @@
package org.klomp.snark;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
@ -20,7 +13,6 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
@ -36,7 +28,6 @@ import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Base32;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.util.ConcurrentHashSet;
@ -45,9 +36,7 @@ import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFile;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SimpleTimer;
import net.i2p.util.SystemVersion;
import net.i2p.util.Translate;
import org.klomp.snark.dht.DHT;
@ -88,7 +77,6 @@ public class I2PSnarkUtil implements DisconnectListener {
private DHT _dht;
private long _startedTime;
private final DisconnectListener _discon;
private int _maxFilesPerTorrent = SnarkManager.DEFAULT_MAX_FILES_PER_TORRENT;
private static final int EEPGET_CONNECT_TIMEOUT = 45*1000;
private static final int EEPGET_CONNECT_TIMEOUT_SHORT = 5*1000;
@ -114,7 +102,7 @@ public class I2PSnarkUtil implements DisconnectListener {
*/
public I2PSnarkUtil(I2PAppContext ctx, String baseName, DisconnectListener discon) {
_context = ctx;
_log = _context.logManager().getLog(I2PSnarkUtil.class);
_log = _context.logManager().getLog(Snark.class);
_baseName = baseName;
_discon = discon;
_opts = new HashMap<String, String>();
@ -254,11 +242,6 @@ public class I2PSnarkUtil implements DisconnectListener {
/** @since 0.9.1 */
public File getTempDir() { return _tmpDir; }
/** @since 0.9.58 */
public int getMaxFilesPerTorrent() { return _maxFilesPerTorrent; }
/** @since 0.9.58 */
public void setMaxFilesPerTorrent(int max) { _maxFilesPerTorrent = Math.max(max, 1); }
/**
* Connect to the router, if we aren't already
*/
@ -364,10 +347,6 @@ public class I2PSnarkUtil implements DisconnectListener {
synchronized(this) {
_manager = null;
_connecting = false;
if (_dht != null) {
_dht.stop();
_dht = null;
}
}
if (_discon != null)
_discon.sessionDisconnected();
@ -577,9 +556,6 @@ public class I2PSnarkUtil implements DisconnectListener {
return null;
}
/**
* Full Base64 of Destination
*/
public String getOurIPString() {
Destination dest = getMyDestination();
if (dest != null)
@ -846,90 +822,4 @@ public class I2PSnarkUtil implements DisconnectListener {
public String getString(int n, String s, String p) {
return Translate.getString(n, s, p, _context, BUNDLE_NAME);
}
private static final boolean SHOULD_SYNC = !(SystemVersion.isAndroid() || SystemVersion.isARM());
private static final Pattern ILLEGAL_KEY = Pattern.compile("[#=\\r\\n;]");
private static final Pattern ILLEGAL_VALUE = Pattern.compile("[\\r\\n]");
/**
* Same as DataHelper.loadProps() but allows '#' in values,
* so we can have filenames with '#' in them in torrent config files.
* '#' must be in column 1 for a comment.
*
* @since 0.9.58
*/
static void loadProps(Properties props, File f) throws IOException {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"), 1024);
String line = null;
while ( (line = in.readLine()) != null) {
if (line.trim().length() <= 0) continue;
if (line.charAt(0) == '#') continue;
if (line.charAt(0) == ';') continue;
int split = line.indexOf('=');
if (split <= 0) continue;
String key = line.substring(0, split);
String val = line.substring(split+1).trim();
props.setProperty(key, val);
}
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
}
}
/**
* Same as DataHelper.loadProps() but allows '#' in values,
* so we can have filenames with '#' in them in torrent config files.
* '#' must be in column 1 for a comment.
*
* @since 0.9.58
*/
static void storeProps(Properties props, File file) throws IOException {
FileOutputStream fos = null;
PrintWriter out = null;
IOException ioe = null;
File tmpFile = new File(file.getPath() + ".tmp");
try {
fos = new SecureFileOutputStream(tmpFile);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(fos, "UTF-8")));
out.println("# NOTE: This I2P config file must use UTF-8 encoding");
out.println("# Last saved: " + DataHelper.formatTime(System.currentTimeMillis()));
for (Map.Entry<Object, Object> entry : props.entrySet()) {
String name = (String) entry.getKey();
String val = (String) entry.getValue();
if (ILLEGAL_KEY.matcher(name).find()) {
if (ioe == null)
ioe = new IOException("Invalid character (one of \"#;=\\r\\n\") in key: \"" +
name + "\" = \"" + val + '\"');
continue;
}
if (ILLEGAL_VALUE.matcher(val).find()) {
if (ioe == null)
ioe = new IOException("Invalid character (one of \"\\r\\n\") in value: \"" +
name + "\" = \"" + val + '\"');
continue;
}
out.println(name + "=" + val);
}
if (SHOULD_SYNC) {
out.flush();
fos.getFD().sync();
}
out.close();
if (out.checkError()) {
out = null;
tmpFile.delete();
throw new IOException("Failed to write properties to " + tmpFile);
}
out = null;
if (!FileUtil.rename(tmpFile, file))
throw new IOException("Failed rename from " + tmpFile + " to " + file);
} finally {
if (out != null) out.close();
if (fos != null) try { fos.close(); } catch (IOException e) {}
}
if (ioe != null)
throw ioe;
}
}

View File

@ -63,7 +63,7 @@ public class MetaInfo
private final int piece_length;
private final byte[] piece_hashes;
private final long length;
private final int privateTorrent; // 0: not present; 1: = 1; -1: = 0
private final boolean privateTorrent;
private final List<List<String>> announce_list;
private final String comment;
private final String created_by;
@ -97,7 +97,7 @@ public class MetaInfo
this.piece_length = piece_length;
this.piece_hashes = piece_hashes;
this.length = length;
this.privateTorrent = privateTorrent ? 1 : 0;
this.privateTorrent = privateTorrent;
this.announce_list = announce_list;
this.comment = comment;
this.created_by = created_by;
@ -117,37 +117,9 @@ public class MetaInfo
//infoMap = null;
}
/**
* Preserves privateTorrent int value, for main()
*
* @since 0.9.62
*/
public MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
int piece_length, byte[] piece_hashes, long length, int privateTorrent,
List<List<String>> announce_list, String created_by, List<String> url_list, String comment)
{
this.announce = announce;
this.name = name;
this.name_utf8 = name_utf8;
this.files = files == null ? null : Collections.unmodifiableList(files);
this.files_utf8 = null;
this.lengths = lengths == null ? null : Collections.unmodifiableList(lengths);
this.piece_length = piece_length;
this.piece_hashes = piece_hashes;
this.length = length;
this.privateTorrent = privateTorrent;
this.announce_list = announce_list;
this.comment = comment;
this.created_by = created_by;
this.creation_date = I2PAppContext.getGlobalContext().clock().now();
this.url_list = url_list;
this.attributes = null;
this.info_hash = calculateInfoHash();
}
/**
* Creates a new MetaInfo from the given InputStream. The
* InputStream must start with a correctly bencoded dictionary
* InputStream must start with a correctly bencoded dictonary
* describing the torrent.
* Caller must close the stream.
*/
@ -172,7 +144,7 @@ public class MetaInfo
/**
* Creates a new MetaInfo from a Map of BEValues and the SHA1 over
* the original bencoded info dictionary (this is a hack, we could
* the original bencoded info dictonary (this is a hack, we could
* reconstruct the bencoded stream and recalculate the hash). Will
* NOT throw a InvalidBEncodingException if the given map does not
* contain a valid announce string.
@ -214,20 +186,11 @@ public class MetaInfo
if (val == null) {
this.url_list = null;
} else {
List<String> urllist;
try {
List<BEValue> bl1 = val.getList();
urllist = new ArrayList<String>(bl1.size());
for (BEValue bev : bl1) {
urllist.add(bev.getString());
}
} catch (InvalidBEncodingException ibee) {
// BEP 19 says it's a list but the example there
// is for a single byte string, and we've seen this
// in the wild.
urllist = Collections.singletonList(val.getString());
List<BEValue> bl1 = val.getList();
this.url_list = new ArrayList<String>(bl1.size());
for (BEValue bev : bl1) {
this.url_list.add(bev.getString());
}
this.url_list = urllist;
}
// misc. optional top-level stuff
@ -285,11 +248,10 @@ public class MetaInfo
// Transmission does numbers. So does libtorrent.
// We handle both as of 0.9.9.
// We switch to storing as number as of 0.9.14.
boolean privat = "1".equals(o) ||
privateTorrent = "1".equals(o) ||
((o instanceof Number) && ((Number) o).intValue() == 1);
privateTorrent = privat ? 1 : -1;
} else {
privateTorrent = 0;
privateTorrent = false;
}
val = info.get("piece length");
@ -506,14 +468,6 @@ public class MetaInfo
* @since 0.9
*/
public boolean isPrivate() {
return privateTorrent > 0;
}
/**
* @return 0 (default), 1 (set to 1), -1 (set to 0)
* @since 0.9.62
*/
public int getPrivateTrackerStatus() {
return privateTorrent;
}
@ -775,10 +729,10 @@ public class MetaInfo
if (name_utf8 != null)
info.put("name.utf-8", new BEValue(DataHelper.getUTF8(name_utf8)));
// BEP 27
if (privateTorrent != 0)
if (privateTorrent)
// switched to number in 0.9.14
//info.put("private", new BEValue(DataHelper.getUTF8("1")));
info.put("private", new BEValue(Integer.valueOf(privateTorrent > 0 ? 1 : 0)));
info.put("private", new BEValue(Integer.valueOf(1)));
info.put("piece length", new BEValue(Integer.valueOf(piece_length)));
info.put("pieces", new BEValue(piece_hashes));
@ -856,7 +810,7 @@ public class MetaInfo
String announce = null;
List<String> url_list = null;
String comment = null;
Getopt g = new Getopt("MetaInfo", args, "a:c:m:w:");
Getopt g = new Getopt("Storage", args, "a:c:m:w:");
try {
int c;
while ((c = g.getopt()) != -1) {
@ -913,7 +867,7 @@ public class MetaInfo
List<String> urls = url_list != null ? url_list : meta.getWebSeedURLs();
// changes/adds creation date
MetaInfo meta2 = new MetaInfo(an, meta.getName(), null, meta.getFiles(), meta.getLengths(),
meta.getPieceLength(0), meta.getPieceHashes(), meta.getTotalLength(), meta.getPrivateTrackerStatus(),
meta.getPieceLength(0), meta.getPieceHashes(), meta.getTotalLength(), meta.isPrivate(),
meta.getAnnounceList(), cb, urls, cm);
java.io.File from = new java.io.File(args[i]);
java.io.File to = new java.io.File(args[i] + ".bak");

View File

@ -2,7 +2,6 @@ package org.klomp.snark;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
@ -44,7 +43,6 @@ class PartialPiece implements Comparable<PartialPiece> {
private RandomAccessFile raf;
private final int pclen;
private final File tempDir;
private final BitField bitfield;
private static final int BUFSIZE = PeerState.PARTSIZE;
private static final ByteCache _cache = ByteCache.getInstance(16, BUFSIZE);
@ -68,7 +66,6 @@ class PartialPiece implements Comparable<PartialPiece> {
this.pclen = len;
//this.createdTime = 0;
this.tempDir = tempDir;
bitfield = new BitField((len + PeerState.PARTSIZE - 1) / PeerState.PARTSIZE);
// temps for finals
byte[] tbs = null;
@ -101,27 +98,22 @@ class PartialPiece implements Comparable<PartialPiece> {
//tfile = SecureFile.createTempFile("piece", null, tempDir);
// debug
tempfile = SecureFile.createTempFile("piece_" + piece.getId() + '_', null, tempDir);
//I2PAppContext.getGlobalContext().logManager().getLog(PartialPiece.class).warn("Created " + tempfile);
// tfile.deleteOnExit() ???
raf = new RandomAccessFile(tempfile, "rw");
// Do not preallocate the file space.
// Not necessary to call setLength(), file is extended when written
//traf.setLength(len);
}
/**
* Convert this PartialPiece to a request for the next chunk.
* Used by PeerState only.
*
* @return null if complete
* Used by PeerState only. This depends on the downloaded value
* as set by setDownloaded() or read().
*/
public synchronized Request getRequest() {
int chunk = off / PeerState.PARTSIZE;
int sz = bitfield.size();
for (int i = chunk; i < sz; i++) {
if (!bitfield.get(i))
return new Request(this, off, Math.min(pclen - off, PeerState.PARTSIZE));
if (i == sz - 1)
off = pclen;
else
off += PeerState.PARTSIZE;
}
return null;
return new Request(this, this.off, Math.min(this.pclen - this.off, PeerState.PARTSIZE));
}
/** piece number */
@ -137,45 +129,28 @@ class PartialPiece implements Comparable<PartialPiece> {
}
/**
* @since 0.9.62
*/
public synchronized boolean isComplete() {
return bitfield.complete();
}
/**
* Have any chunks been downloaded?
*
* @since 0.9.63
*/
public synchronized boolean hasData() {
return bitfield.count() > 0;
}
/**
* Has this chunk been downloaded?
*
* @since 0.9.63
*/
public synchronized boolean hasChunk(int chunk) {
return bitfield.get(chunk);
}
/**
* How many bytes are good - as set by read().
* As of 0.9.63, accurately counts good bytes after "holes".
* How many bytes are good - as set by setDownloaded() or read()
*/
public synchronized int getDownloaded() {
if (bitfield.complete())
return pclen;
int sz = bitfield.count();
int rv = sz * PeerState.PARTSIZE;
int rem = pclen % PeerState.PARTSIZE;
if (rem != 0 && bitfield.get(sz - 1))
rv -= PeerState.PARTSIZE - rem;
return rv;
return this.off;
}
/**
* Call this if necessary before returning a PartialPiece to the PeerCoordinator.
* We do not use a bitmap to track individual chunks received.
* Any chunks after a 'hole' will be lost.
* @since 0.9.1
*/
public synchronized void setDownloaded(int offset) {
this.off = offset;
}
/****
public long getCreated() {
return this.createdTime;
}
****/
/**
* Piece must be complete.
* The SHA1 hash of the completely read data.
@ -225,47 +200,13 @@ class PartialPiece implements Comparable<PartialPiece> {
*
* @since 0.9.1
*/
public void read(DataInputStream din, int offset, int len, BandwidthListener bwl) throws IOException {
if (offset % PeerState.PARTSIZE != 0)
throw new IOException("Bad offset " + offset);
int chunk = offset / PeerState.PARTSIZE;
// We read the data before checking if we have the chunk,
// because otherwise we'd have to break the peer connection
public void read(DataInputStream din, int offset, int len) throws IOException {
if (bs != null) {
// Don't use readFully() so we may update the BandwidthListener as we go
//in.readFully(bs, offset, len);
int offs = offset;
int toRead = len;
while (toRead > 0) {
int numRead = din.read(bs, offs, toRead);
if (numRead < 0)
throw new EOFException();
offs += numRead;
toRead -= numRead;
bwl.downloaded(numRead);
}
din.readFully(bs, offset, len);
synchronized (this) {
if (bitfield.get(chunk)) {
warn("Already have chunk " + chunk + " on " + this);
} else {
bitfield.set(chunk);
if (this.off == offset) {
this.off += len;
// if this filled in a hole, advance off
int sz = bitfield.size();
for (int i = chunk + 1; i < sz; i++) {
if (!bitfield.get(i))
break;
warn("Hole filled in before chunk " + i + " on " + this + ' ' + bitfield);
if (i == sz - 1)
off = pclen;
else
off += PeerState.PARTSIZE;
}
} else {
warn("Out of order chunk " + chunk + " on " + this + ' ' + bitfield);
}
}
// only works for in-order chunks
if (this.off == offset)
this.off += len;
}
} else {
// read in fully before synching on raf
@ -278,46 +219,15 @@ class PartialPiece implements Comparable<PartialPiece> {
ba = null;
tmp = new byte[len];
}
// Don't use readFully() so we may update the BandwidthListener as we go
//din.readFully(tmp);
int offs = 0;
int toRead = len;
while (toRead > 0) {
int numRead = din.read(tmp, offs, toRead);
if (numRead < 0)
throw new EOFException();
offs += numRead;
toRead -= numRead;
bwl.downloaded(numRead);
}
din.readFully(tmp);
synchronized (this) {
if (bitfield.get(chunk)) {
warn("Already have chunk " + chunk + " on " + this);
} else {
if (raf == null)
createTemp();
raf.seek(offset);
raf.write(tmp);
bitfield.set(chunk);
if (this.off == offset) {
this.off += len;
// if this filled in a hole, advance off
int sz = bitfield.size();
for (int i = chunk + 1; i < sz; i++) {
if (!bitfield.get(i))
break;
warn("Hole filled in before chunk " + i + " on " + this + ' ' + bitfield);
if (i == sz - 1)
off = pclen;
else
off += PeerState.PARTSIZE;
}
} else {
warn("Out of order chunk " + chunk + " on " + this + ' ' + bitfield);
}
}
if (raf == null)
createTemp();
raf.seek(offset);
raf.write(tmp);
// only works for in-order chunks
if (this.off == offset)
this.off += len;
}
if (ba != null)
_cache.release(ba, false);
@ -373,10 +283,8 @@ class PartialPiece implements Comparable<PartialPiece> {
public void release() {
if (bs == null) {
synchronized (this) {
if (raf != null) {
if (raf != null)
locked_release();
raf = null;
}
}
//if (raf != null)
// I2PAppContext.getGlobalContext().logManager().getLog(PartialPiece.class).warn("Released " + tempfile);
@ -392,6 +300,7 @@ class PartialPiece implements Comparable<PartialPiece> {
try {
raf.close();
} catch (IOException ioe) {
I2PAppContext.getGlobalContext().logManager().getLog(PartialPiece.class).warn("Error closing " + raf, ioe);
}
tempfile.delete();
}
@ -405,7 +314,7 @@ class PartialPiece implements Comparable<PartialPiece> {
int d = this.piece.compareTo(opp.piece);
if (d != 0)
return d;
return opp.getDownloaded() - getDownloaded(); // reverse
return opp.off - this.off; // reverse
}
@Override
@ -428,13 +337,6 @@ class PartialPiece implements Comparable<PartialPiece> {
@Override
public String toString() {
return "Partial(" + piece.getId() + ',' + off + ',' + getDownloaded() + ',' + pclen + ')';
}
/**
* @since 0.9.62
*/
public static void warn(String s) {
I2PAppContext.getGlobalContext().logManager().getLog(PartialPiece.class).warn(s);
return "Partial(" + piece.getId() + ',' + off + ',' + pclen + ')';
}
}

View File

@ -40,7 +40,7 @@ import net.i2p.util.Log;
import org.klomp.snark.bencode.BEValue;
import org.klomp.snark.bencode.InvalidBEncodingException;
public class Peer implements Comparable<Peer>, BandwidthListener
public class Peer implements Comparable<Peer>
{
protected final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
// Identifying property, the peer id of the other side.
@ -96,8 +96,6 @@ public class Peer implements Comparable<Peer>, BandwidthListener
private final boolean _isIncoming;
private int _totalCommentsSent;
private int _maxPipeline = PeerState.MIN_PIPELINE;
private long connected;
private long pexLastSent;
/**
* Outgoing connection.
@ -241,7 +239,7 @@ public class Peer implements Comparable<Peer>, BandwidthListener
*
* @param uploadOnly if we are complete with skipped files, i.e. a partial seed
*/
public void runConnection(I2PSnarkUtil util, PeerListener listener, BandwidthListener bwl, BitField bitfield,
public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField bitfield,
MagnetState mState, boolean uploadOnly) {
if (state != null)
throw new IllegalStateException("Peer already started");
@ -290,7 +288,7 @@ public class Peer implements Comparable<Peer>, BandwidthListener
PeerConnectionIn in = new PeerConnectionIn(this, din);
PeerConnectionOut out = new PeerConnectionOut(this, dout);
PeerState s = new PeerState(this, listener, bwl, metainfo, in, out);
PeerState s = new PeerState(this, listener, metainfo, in, out);
if ((options & OPTION_EXTENSION) != 0) {
if (_log.shouldLog(Log.DEBUG))
@ -309,7 +307,6 @@ public class Peer implements Comparable<Peer>, BandwidthListener
// We are up and running!
state = s;
magnetState = mState;
connected = util.getContext().clock().now();
listener.connected(this);
if (_log.shouldLog(Log.DEBUG))
@ -654,17 +651,12 @@ public class Peer implements Comparable<Peer>, BandwidthListener
return (s == null) || s.choked;
}
/////// begin BandwidthListener interface ///////
/**
* Increment the counter.
* @since 0.8.4
*/
public void downloaded(int size) {
downloaded.addAndGet(size);
PeerState s = state;
if (s != null)
s.getBandwidthListener().downloaded(size);
}
/**
@ -673,9 +665,6 @@ public class Peer implements Comparable<Peer>, BandwidthListener
*/
public void uploaded(int size) {
uploaded.addAndGet(size);
PeerState s = state;
if (s != null)
s.getBandwidthListener().uploaded(size);
}
/**
@ -699,115 +688,13 @@ public class Peer implements Comparable<Peer>, BandwidthListener
}
/**
* Returns the average rate in Bps
*/
public long getUploadRate()
{
return PeerCoordinator.getRate(uploaded_old);
}
public long getDownloadRate()
{
return PeerCoordinator.getRate(downloaded_old);
}
/**
* Should we send this many bytes?
* Do NOT call uploaded() after this.
* @since 0.9.62
*/
public boolean shouldSend(int size) {
PeerState s = state;
if (s != null) {
boolean rv = s.getBandwidthListener().shouldSend(size);
if (rv)
uploaded.addAndGet(size);
return rv;
}
return false;
}
/**
* Should we request this many bytes?
* @since 0.9.62
*/
public boolean shouldRequest(int size) {
PeerState s = state;
if (s != null)
return s.getBandwidthListener().shouldRequest(this, size);
return false;
}
/**
* Should we request this many bytes?
* @since 0.9.62
*/
public boolean shouldRequest(Peer peer, int size) {
if (peer != this)
return false;
PeerState s = state;
if (s != null)
return s.getBandwidthListener().shouldRequest(this, size);
return false;
}
/**
* Current limit in Bps
* @since 0.9.62
*/
public long getUpBWLimit() {
PeerState s = state;
if (s != null)
return s.getBandwidthListener().getUpBWLimit();
return Integer.MAX_VALUE;
}
/**
* Is snark as a whole over its limit?
* @since 0.9.62
*/
public boolean overUpBWLimit()
{
PeerState s = state;
if (s != null)
return s.getBandwidthListener().overUpBWLimit();
return false;
}
/**
* Current limit in Bps
* @since 0.9.62
*/
public long getDownBWLimit() {
PeerState s = state;
if (s != null)
return s.getBandwidthListener().getDownBWLimit();
return Integer.MAX_VALUE;
}
/**
* Are we currently over the limit?
* @since 0.9.62
*/
public boolean overDownBWLimit() {
PeerState s = state;
if (s != null)
return s.getBandwidthListener().overDownBWLimit();
return false;
}
/**
* Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
* Resets the downloaded and uploaded counters to zero.
*/
void setRateHistory() {
long up = uploaded.getAndSet(0);
PeerCoordinator.setRate(up, uploaded_old);
long down = downloaded.getAndSet(0);
PeerCoordinator.setRate(down, downloaded_old);
public void resetCounters()
{
downloaded.set(0);
uploaded.set(0);
}
/////// end BandwidthListener interface ///////
public long getInactiveTime() {
PeerState s = state;
@ -874,6 +761,28 @@ public class Peer implements Comparable<Peer>, BandwidthListener
return s.bitfield.complete();
}
/**
* Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
*/
public void setRateHistory(long up, long down)
{
PeerCoordinator.setRate(up, uploaded_old);
PeerCoordinator.setRate(down, downloaded_old);
}
/**
* Returns the 4-minute-average rate in Bps
*/
public long getUploadRate()
{
return PeerCoordinator.getRate(uploaded_old);
}
public long getDownloadRate()
{
return PeerCoordinator.getRate(downloaded_old);
}
/** @since 0.9.31 */
int getTotalCommentsSent() {
return _totalCommentsSent;
@ -891,28 +800,4 @@ public class Peer implements Comparable<Peer>, BandwidthListener
public boolean isWebPeer() {
return false;
}
/**
* when did handshake complete?
* @since 0.9.63
*/
public long getWhenConnected() {
return connected;
}
/**
* when did we last send pex peers?
* @since 0.9.63
*/
public long getPexLastSent() {
return pexLastSent;
}
/**
* when did we last send pex peers?
* @since 0.9.63
*/
public void setPexLastSent(long now) {
pexLastSent = now;
}
}

View File

@ -113,7 +113,8 @@ class PeerCheckerTask implements Runnable
uploaded += upload;
long download = peer.getDownloaded();
downloaded += download;
peer.setRateHistory();
peer.setRateHistory(upload, download);
peer.resetCounters();
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(peer + ":"
@ -126,9 +127,10 @@ class PeerCheckerTask implements Runnable
}
// Choke a percentage of them rather than all so it isn't so drastic...
// choke 3/8 of the time when seeding and 1/4 when leeching
// unless this torrent is over the limit all by itself.
// choke 5/8 of the time when seeding and 3/8 when leeching
boolean overBWLimitChoke = upload > 0 &&
((overBWLimit && (random.nextInt(8) > (coordinator.completed() ? 4 : 5))) ||
((overBWLimit && (random.nextInt(8) > (coordinator.completed() ? 2 : 4))) ||
(coordinator.overUpBWLimit(uploaded)));
// If we are at our max uploaders and we have lots of other

View File

@ -157,7 +157,7 @@ class PeerConnectionIn implements Runnable
Request req = ps.getOutstandingRequest(piece, begin, len);
if (req != null)
{
req.read(din, peer);
req.read(din);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Received data(" + piece + "," + begin + ") from " + peer);
ps.pieceMessage(req);

View File

@ -73,7 +73,6 @@ class PeerConnectionOut implements Runnable
{
try
{
boolean shouldThrottleRequests = false;
while (!quit && peer.isConnected())
{
Message m = null;
@ -90,7 +89,7 @@ class PeerConnectionOut implements Runnable
synchronized(sendQueue)
{
while (!quit && peer.isConnected() && (shouldThrottleRequests || sendQueue.isEmpty()))
while (!quit && peer.isConnected() && sendQueue.isEmpty())
{
try
{
@ -99,13 +98,12 @@ class PeerConnectionOut implements Runnable
// dout.flush();
// Wait till more data arrives.
sendQueue.wait(shouldThrottleRequests ? 5000 : 60*1000);
sendQueue.wait(60*1000);
}
catch (InterruptedException ie)
{
/* ignored */
}
shouldThrottleRequests = false;
}
state = peer.state;
if (!quit && state != null && peer.isConnected())
@ -127,6 +125,7 @@ class PeerConnectionOut implements Runnable
{
if (state.choking) {
it.remove();
//SimpleTimer.getInstance().removeEvent(nm.expireEvent);
if (peer.supportsFast()) {
Message r = new Message(Message.REJECT, nm.piece, nm.begin, nm.length);
if (_log.shouldLog(Log.DEBUG))
@ -136,50 +135,23 @@ class PeerConnectionOut implements Runnable
}
nm = null;
}
else if (nm.type == Message.REQUEST)
else if (nm.type == Message.REQUEST && state.choked)
{
if (state.choked) {
it.remove();
nm = null;
} else if (shouldThrottleRequests) {
// previous request in queue throttled, skip this one too
if (_log.shouldWarn())
_log.warn("Additional throttle: " + nm + " to " + peer);
nm = null;
} else if (!peer.shouldRequest(nm.length)) {
// request throttle, skip this and all others in this loop
if (_log.shouldWarn())
_log.warn("Throttle: " + nm + " to " + peer);
shouldThrottleRequests = true;
nm = null;
}
it.remove();
//SimpleTimer.getInstance().removeEvent(nm.expireEvent);
nm = null;
}
if (nm != null)
{
m = nm;
//SimpleTimer.getInstance().removeEvent(nm.expireEvent);
it.remove();
}
}
if (m == null) {
m = sendQueue.peek();
if (m != null && m.type == Message.PIECE) {
// bandwidth limiting
// Pieces are the last thing in the queue to be sent so we can
// simply wait right here and then loop
if (!peer.shouldSend(Math.min(m.length, PeerState.PARTSIZE))) {
if (_log.shouldWarn())
_log.warn("Throttle: " + m + " to " + peer);
try {
sendQueue.wait(5000);
} catch (InterruptedException ie) {}
continue;
}
} else if (m != null && m.type == Message.REQUEST) {
if (shouldThrottleRequests)
continue;
}
m = sendQueue.poll();
m = sendQueue.poll();
//SimpleTimer.getInstance().removeEvent(m.expireEvent);
}
}
}
@ -206,14 +178,17 @@ class PeerConnectionOut implements Runnable
// only count the rest of the upload after sendMessage().
int remainder = 0;
if (m.type == Message.PIECE) {
// first PARTSIZE was signalled in shouldSend() above
if (m.len > PeerState.PARTSIZE)
if (m.len <= PeerState.PARTSIZE) {
state.uploaded(m.len);
} else {
state.uploaded(PeerState.PARTSIZE);
remainder = m.len - PeerState.PARTSIZE;
}
}
m.sendMessage(dout);
if (remainder > 0)
peer.uploaded(remainder);
state.uploaded(remainder);
m = null;
}
}

View File

@ -55,7 +55,7 @@ import org.klomp.snark.dht.DHT;
/**
* Coordinates what peer does what.
*/
class PeerCoordinator implements PeerListener, BandwidthListener
class PeerCoordinator implements PeerListener
{
private final Log _log;
@ -124,12 +124,6 @@ class PeerCoordinator implements PeerListener, BandwidthListener
/** Timer to handle all periodical tasks. */
private final CheckEvent timer;
// RerequestEvent and related values
private final SimpleTimer2.TimedEvent rerequestTimer;
private final Object rerequestLock = new Object();
private boolean wasRequestAllowed;
private boolean isRerequestScheduled;
private final byte[] id;
private final byte[] infohash;
@ -151,7 +145,6 @@ class PeerCoordinator implements PeerListener, BandwidthListener
private final MagnetState magnetState;
private final CoordinatorListener listener;
private final BandwidthListener bwListener;
private final I2PSnarkUtil _util;
private final RandomSource _random;
@ -170,7 +163,7 @@ class PeerCoordinator implements PeerListener, BandwidthListener
* @param storage null if in magnet mode
*/
public PeerCoordinator(I2PSnarkUtil util, byte[] id, byte[] infohash, MetaInfo metainfo, Storage storage,
CoordinatorListener listener, Snark torrent, BandwidthListener bwl)
CoordinatorListener listener, Snark torrent)
{
_util = util;
_random = util.getContext().random();
@ -181,7 +174,6 @@ class PeerCoordinator implements PeerListener, BandwidthListener
this.storage = storage;
this.listener = listener;
this.snark = torrent;
bwListener = bwl;
wantedPieces = new ArrayList<Piece>();
setWantedPieces();
@ -196,9 +188,6 @@ class PeerCoordinator implements PeerListener, BandwidthListener
timer = new CheckEvent(_util.getContext(), new PeerCheckerTask(_util, this));
timer.schedule((CHECK_PERIOD / 2) + _random.nextInt((int) CHECK_PERIOD));
// NOT scheduled until needed
rerequestTimer = new RerequestEvent();
// we don't store the last-requested time, so just delay a random amount
_commentsLastRequested.set(util.getContext().clock().now() - (COMMENT_REQ_INTERVAL - _random.nextLong(COMMENT_REQ_DELAY)));
}
@ -219,42 +208,6 @@ class PeerCoordinator implements PeerListener, BandwidthListener
}
}
/**
* Rerequest after unthrottled
* @since 0.9.62
*/
private class RerequestEvent extends SimpleTimer2.TimedEvent {
/** caller must schedule */
public RerequestEvent() {
super(_util.getContext().simpleTimer2());
}
public void timeReached() {
if (bwListener.shouldRequest(null, 0)) {
if (_log.shouldWarn())
_log.warn("Now unthrottled, rerequest timer poking all peers");
// so shouldRequest() won't fire us up again
synchronized(rerequestLock) {
wasRequestAllowed = true;
}
for (Peer p : peers) {
if (p.isInteresting() && !p.isChoked())
p.request();
}
synchronized(rerequestLock) {
isRerequestScheduled = false;
}
} else {
if (_log.shouldWarn())
_log.warn("Still throttled, rerequest timer reschedule");
synchronized(rerequestLock) {
wasRequestAllowed = false;
}
schedule(2*1000);
}
}
}
/**
* Only called externally from Storage after the double-check fails.
* Sets wantedBytes too.
@ -375,78 +328,6 @@ class PeerCoordinator implements PeerListener, BandwidthListener
return downloaded.get();
}
/////// begin BandwidthListener interface ///////
/**
* Called when a peer has uploaded some bytes of a piece.
* @since 0.9.62 params changed
*/
public void uploaded(int size) {
uploaded.addAndGet(size);
bwListener.uploaded(size);
}
/**
* Called when a peer has downloaded some bytes of a piece.
* @since 0.9.62 params changed
*/
public void downloaded(int size) {
downloaded.addAndGet(size);
bwListener.downloaded(size);
}
/**
* Should we send this many bytes?
* Do NOT call uploaded() if this returns true.
* @since 0.9.62
*/
public boolean shouldSend(int size) {
boolean rv = bwListener.shouldSend(size);
if (rv)
uploaded.addAndGet(size);
return rv;
}
/**
* Should we request this many bytes?
* @since 0.9.62
*/
public boolean shouldRequest(Peer peer, int size) {
boolean rv;
synchronized(rerequestLock) {
rv = bwListener.shouldRequest(peer, size);
if (!wasRequestAllowed && rv) {
// we weren't allowed and now we are
if (isRerequestScheduled) {
// just let the timer run when scheduled, do not pull it in
// to prevent thrashing
//if (_log.shouldWarn())
// _log.warn("Now unthrottled, BUT DON'T reschedule rerequest timer");
} else {
// schedule the timer
// we still have to throw it to the timer so we don't loop
if (_log.shouldWarn())
_log.warn("Now unthrottled, schedule rerequest timer");
isRerequestScheduled = true;
// no rush, wait at little while
rerequestTimer.reschedule(1000);
}
wasRequestAllowed = true;
} else if (wasRequestAllowed && !rv) {
// we were allowed and now we aren't
if (!isRerequestScheduled) {
// schedule the timer
if (_log.shouldWarn())
_log.warn("Now throttled, schedule rerequest timer");
isRerequestScheduled = true;
rerequestTimer.schedule(3*1000);
}
wasRequestAllowed = false;
}
}
return rv;
}
/**
* Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
*/
@ -521,49 +402,6 @@ class PeerCoordinator implements PeerListener, BandwidthListener
return rate / (factor * CHECK_PERIOD / 1000);
}
/**
* Current limit in Bps
* @since 0.9.62
*/
public long getUpBWLimit() {
return bwListener.getUpBWLimit();
}
/**
* Is snark as a whole over its limit?
*/
public boolean overUpBWLimit()
{
return bwListener.overUpBWLimit();
}
/**
* Is a particular peer who has downloaded this many bytes from us
* in the last CHECK_PERIOD over its limit?
*/
public boolean overUpBWLimit(long total)
{
return total * 1000 / CHECK_PERIOD > getUpBWLimit();
}
/**
* Current limit in Bps
* @since 0.9.62
*/
public long getDownBWLimit() {
return bwListener.getDownBWLimit();
}
/**
* Are we currently over the limit?
* @since 0.9.62
*/
public boolean overDownBWLimit() {
return bwListener.overDownBWLimit();
}
/////// end BandwidthListener interface ///////
public MetaInfo getMetaInfo()
{
return metainfo;
@ -614,12 +452,10 @@ class PeerCoordinator implements PeerListener, BandwidthListener
if (metainfo == null)
return 6;
int pieces = metainfo.getPieces();
if (pieces <= 10)
if (pieces <= 2)
return 4;
if (pieces <= 25)
return 10;
if (pieces <= 80)
return 16;
if (pieces <= 5)
return 6;
//int size = metainfo.getPieceLength(0);
int max = _util.getMaxConnections();
// Now that we use temp files, no memory concern
@ -821,7 +657,7 @@ class PeerCoordinator implements PeerListener, BandwidthListener
{
public void run()
{
peer.runConnection(_util, listener, PeerCoordinator.this, bitfield, magnetState, partialComplete);
peer.runConnection(_util, listener, bitfield, magnetState, partialComplete);
}
};
String threadName = "Snark peer " + peer.toString();
@ -845,8 +681,6 @@ class PeerCoordinator implements PeerListener, BandwidthListener
{
if (storage == null || storage.getBitField().size() == 0)
return;
if (overUpBWLimit())
return;
// linked list will contain all interested peers that we choke.
// At the start are the peers that have us unchoked at the end the
@ -944,6 +778,15 @@ class PeerCoordinator implements PeerListener, BandwidthListener
*/
private static final int MAX_PARALLEL_REQUESTS = 4;
/**
* Returns one of pieces in the given BitField that is still wanted or
* -1 if none of the given pieces are wanted.
*/
public int wantPiece(Peer peer, BitField havePieces) {
Piece pc = wantPiece(peer, havePieces, true);
return pc != null ? pc.getId() : -1;
}
/**
* Returns one of pieces in the given BitField that is still wanted or
* null if none of the given pieces are wanted.
@ -1160,6 +1003,28 @@ class PeerCoordinator implements PeerListener, BandwidthListener
}
}
/**
* Called when a peer has uploaded some bytes of a piece.
*/
public void uploaded(Peer peer, int size)
{
uploaded.addAndGet(size);
//if (listener != null)
// listener.peerChange(this, peer);
}
/**
* Called when a peer has downloaded some bytes of a piece.
*/
public void downloaded(Peer peer, int size)
{
downloaded.addAndGet(size);
//if (listener != null)
// listener.peerChange(this, peer);
}
/**
* Returns false if the piece is no good (according to the hash).
* In that case the peer that supplied the piece should probably be
@ -1294,7 +1159,7 @@ class PeerCoordinator implements PeerListener, BandwidthListener
}
if (uploaders.get() < allowedUploaders())
{
if(peer.isChoking() && !overUpBWLimit())
if(peer.isChoking())
{
uploaders.incrementAndGet();
interestedUploaders.incrementAndGet();
@ -1352,7 +1217,7 @@ class PeerCoordinator implements PeerListener, BandwidthListener
* Also mark the piece unrequested if this peer was the only one.
*
* @param peer partials, must include the zero-offset (empty) ones too.
* No dup pieces.
* No dup pieces, piece.setDownloaded() must be set.
* len field in Requests is ignored.
* @since 0.8.2
*/
@ -1370,14 +1235,14 @@ class PeerCoordinator implements PeerListener, BandwidthListener
synchronized(wantedPieces) {
for (Request req : partials) {
PartialPiece pp = req.getPartialPiece();
if (pp.hasData()) {
if (req.off > 0) {
// PartialPiece.equals() only compares piece number, which is what we want
int idx = partialPieces.indexOf(pp);
if (idx < 0) {
partialPieces.add(pp);
if (_log.shouldLog(Log.INFO))
_log.info("Saving orphaned partial piece (new) " + pp);
} else if (pp.getDownloaded() > partialPieces.get(idx).getDownloaded()) {
} else if (idx >= 0 && pp.getDownloaded() > partialPieces.get(idx).getDownloaded()) {
// replace what's there now
partialPieces.get(idx).release();
partialPieces.set(idx, pp);
@ -1434,9 +1299,7 @@ class PeerCoordinator implements PeerListener, BandwidthListener
for(Piece piece : wantedPieces) {
if (piece.getId() == savedPiece) {
if (peer.isCompleted() && piece.getPeerCount() > 1 &&
wantedPieces.size() > 2*END_GAME_THRESHOLD &&
partialPieces.size() < 4 &&
_random.nextInt(4) != 0) {
wantedPieces.size() > 2*END_GAME_THRESHOLD) {
// Try to preserve rarest-first
// by not requesting a partial piece that at least two non-seeders also have
// from a seeder
@ -1464,7 +1327,7 @@ class PeerCoordinator implements PeerListener, BandwidthListener
iter.remove();
piece.setRequested(peer, true);
if (_log.shouldLog(Log.INFO)) {
_log.info("Restoring orphaned partial piece " + pp + " to " + peer +
_log.info("Restoring orphaned partial piece " + pp +
" Partial list size now: " + partialPieces.size());
}
return pp;
@ -1576,9 +1439,7 @@ class PeerCoordinator implements PeerListener, BandwidthListener
}
}
} else if (id == ExtensionHandler.ID_HANDSHAKE) {
// We may not have the bitfield yet, but if we do, don't send PEX to seeds
if (!peer.isCompleted())
sendPeers(peer);
sendPeers(peer);
sendDHT(peer);
if (_util.utCommentsEnabled())
sendCommentReq(peer);
@ -1587,8 +1448,8 @@ class PeerCoordinator implements PeerListener, BandwidthListener
/**
* Send a PEX message to the peer, if he supports PEX.
* This sends everybody we have connected to since the
* last time we sent PEX to him.
* This just sends everybody we are connected to, we don't
* track new vs. old peers yet.
* @since 0.8.4
*/
void sendPeers(Peer peer) {
@ -1602,25 +1463,14 @@ class PeerCoordinator implements PeerListener, BandwidthListener
return;
try {
if (bev.getMap().get(ExtensionHandler.TYPE_PEX) != null) {
List<Peer> pList = new ArrayList<Peer>();
long t = peer.getPexLastSent();
for (Peer p : peers) {
if (p.equals(peer))
continue;
if (p.isWebPeer())
continue;
if (p.getWhenConnected() > t)
pList.add(p);
List<Peer> pList = peerList();
pList.remove(peer);
for (Iterator<Peer> iter = pList.iterator(); iter.hasNext(); ) {
if (iter.next().isWebPeer())
iter.remove();
}
if (!pList.isEmpty()) {
if (!pList.isEmpty())
ExtensionHandler.sendPEX(peer, pList);
peer.setPexLastSent(_util.getContext().clock().now());
//if (_log.shouldDebug())
// _log.debug("Pex: sent " + pList.size() + " new peers to " + peer);
//} else {
//if (_log.shouldDebug())
// _log.debug("Pex: no new peers to send to " + peer);
}
}
} catch (InvalidBEncodingException ibee) {}
}
@ -1888,6 +1738,27 @@ class PeerCoordinator implements PeerListener, BandwidthListener
interestedAndChoking.addAndGet(toAdd);
}
/**
* Is snark as a whole over its limit?
*/
public boolean overUpBWLimit()
{
if (listener != null)
return listener.overUpBWLimit();
return false;
}
/**
* Is a particular peer who has downloaded this many bytes from us
* in the last CHECK_PERIOD over its limit?
*/
public boolean overUpBWLimit(long total)
{
if (listener != null)
return listener.overUpBWLimit(total * 1000 / CHECK_PERIOD);
return false;
}
/**
* Convenience
* @since 0.9.2

View File

@ -120,6 +120,36 @@ interface PeerListener
*/
ByteArray gotRequest(Peer peer, int piece, int off, int len);
/**
* Called when a (partial) piece has been downloaded from the peer.
*
* @param peer the Peer from which size bytes where downloaded.
* @param size the number of bytes that where downloaded.
*/
void downloaded(Peer peer, int size);
/**
* Called when a (partial) piece has been uploaded to the peer.
*
* @param peer the Peer to which size bytes where uploaded.
* @param size the number of bytes that where uploaded.
*/
void uploaded(Peer peer, int size);
/**
* Called when we are downloading from the peer and need to ask for
* a new piece. Might be called multiple times before
* <code>gotPiece()</code> is called.
*
* @param peer the Peer that will be asked to provide the piece.
* @param bitfield a BitField containing the pieces that the other
* side has.
*
* @return one of the pieces from the bitfield that we want or -1 if
* we are no longer interested in the peer.
*/
int wantPiece(Peer peer, BitField bitfield);
/**
* Called when we are downloading from the peer and may need to ask for
* a new piece. Returns true if wantPiece() or getPartialPiece() would return a piece.

View File

@ -41,7 +41,6 @@ class PeerState implements DataLoader
private final Peer peer;
/** Fixme, used by Peer.disconnect() to get to the coordinator */
final PeerListener listener;
private final BandwidthListener bwListener;
/** Null before we have it. locking: this */
private MetaInfo metainfo;
/** Null unless needed. Contains -1 for all. locking: this */
@ -67,8 +66,7 @@ class PeerState implements DataLoader
// Outstanding request
private final List<Request> outstandingRequests = new ArrayList<Request>();
/** the tail (NOT the head) of the request queue */
private Request lastRequest;
private int currentMaxPipeline;
private Request lastRequest = null;
// FIXME if piece size < PARTSIZE, pipeline could be bigger
/** @since 0.9.47 */
@ -83,23 +81,17 @@ class PeerState implements DataLoader
/**
* @param metainfo null if in magnet mode
*/
PeerState(Peer peer, PeerListener listener, BandwidthListener bwl, MetaInfo metainfo,
PeerState(Peer peer, PeerListener listener, MetaInfo metainfo,
PeerConnectionIn in, PeerConnectionOut out)
{
this.peer = peer;
this.listener = listener;
bwListener = bwl;
this.metainfo = metainfo;
this.in = in;
this.out = out;
}
/**
* @since 0.9.62
*/
BandwidthListener getBandwidthListener() { return bwListener; }
// NOTE Methods that inspect or change the state synchronize (on this).
void keepAliveMessage()
@ -397,6 +389,7 @@ class PeerState implements DataLoader
void uploaded(int size)
{
peer.uploaded(size);
listener.uploaded(peer, size);
}
// This is used to flag that we have to back up from the firstOutstandingRequest
@ -415,8 +408,8 @@ class PeerState implements DataLoader
void pieceMessage(Request req)
{
int size = req.len;
// Now reported byte-by-byte in PartialPiece
//peer.downloaded(size);
peer.downloaded(size);
listener.downloaded(peer, size);
if (_log.shouldLog(Log.DEBUG))
_log.debug("got end of Chunk("
@ -424,12 +417,11 @@ class PeerState implements DataLoader
+ peer);
// Last chunk needed for this piece?
PartialPiece pp = req.getPartialPiece();
boolean complete = pp.isComplete();
if (complete)
// FIXME if priority changed to skip, we will think we're done when we aren't
if (getFirstOutstandingRequest(req.getPiece()) == -1)
{
// warning - may block here for a while
if (listener.gotPiece(peer, pp))
if (listener.gotPiece(peer, req.getPartialPiece()))
{
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got " + req.getPiece() + ": " + peer);
@ -450,31 +442,9 @@ class PeerState implements DataLoader
synchronized(this) {
pendingRequest = null;
}
// getOutstandingRequest() was called by PeerConnectionIn at the start of the chunk;
// if the bandwidth limiter throttled us to zero requests then, try again now
if (outstandingRequests.isEmpty()) {
addRequest();
if (!complete) {
synchronized(this) {
if (outstandingRequests.isEmpty()) {
// we MUST return the partial piece to PeerCoordinator,
// or else we will lose it and leak the data
if (_log.shouldWarn())
_log.warn("Throttled, returned to coord. w/ data " + req);
List<Request> pcs = Collections.singletonList(req);
listener.savePartialPieces(this.peer, pcs);
lastRequest = null;
}
}
}
}
}
/**
* TODO this is how we tell we got all the chunks in pieceMessage() above.
*
*
* @return index in outstandingRequests or -1
*/
synchronized private int getFirstOutstandingRequest(int piece)
@ -597,8 +567,15 @@ class PeerState implements DataLoader
List<Request> rv = new ArrayList<Request>(pcs.size());
for (Integer p : pcs) {
Request req = getLowestOutstandingRequest(p.intValue());
if (req != null)
if (req != null) {
PartialPiece pp = req.getPartialPiece();
synchronized(pp) {
int dl = pp.getDownloaded();
if (req.off != dl)
req = new Request(pp, dl);
}
rv.add(req);
}
}
outstandingRequests.clear();
pendingRequest = null;
@ -722,6 +699,12 @@ class PeerState implements DataLoader
/**
* BEP 6
* If the peer rejects lower chunks but not higher ones, thus creating holes,
* we won't figure it out and the piece will fail, since we don't currently
* keep a chunk bitmap in PartialPiece.
* As long as the peer rejects all the chunks, or rejects only the last chunks,
* no holes are created and we will be fine. The reject messages may be in any order,
* just don't make a hole when it's over.
*
* @since 0.9.21
*/
@ -745,10 +728,19 @@ class PeerState implements DataLoader
}
}
if (deletedRequest != null && !haveMoreRequests) {
List<Request> pcs = Collections.singletonList(deletedRequest);
// We must return the piece to the coordinator
// Create a new fake request so we can set the offset correctly
PartialPiece pp = deletedRequest.getPartialPiece();
int downloaded = pp.getDownloaded();
Request req;
if (deletedRequest.off == downloaded)
req = deletedRequest;
else
req = new Request(pp, downloaded, 1);
List<Request> pcs = Collections.singletonList(req);
listener.savePartialPieces(this.peer, pcs);
if (_log.shouldWarn())
_log.warn("Returned to coord. w/ data " + deletedRequest.getPartialPiece().getDownloaded() + " due to reject(" + piece + ',' + begin + ',' + length + ") from " + peer);
_log.warn("Returned to coord. w/ offset " + pp.getDownloaded() + " due to reject(" + piece + ',' + begin + ',' + length + ") from " + peer);
}
if (lastRequest != null && lastRequest.getPiece() == piece &&
lastRequest.off == begin && lastRequest.len == length)
@ -874,108 +866,72 @@ class PeerState implements DataLoader
*
* This is called from several places:
*<pre>
* By getOutstandingRequest() when the first part of a chunk comes in
* By getOustandingRequest() when the first part of a chunk comes in
* By havePiece() when somebody got a new piece completed
* By chokeMessage() when we receive an unchoke
* By setInteresting() when we are now interested
* By PeerCoordinator.updatePiecePriorities()
*</pre>
*/
void addRequest()
synchronized void addRequest()
{
// no bitfield yet? nothing to request then.
if (bitfield == null)
return;
if (metainfo == null)
return;
// Initial bw check. We do the actual accounting in PeerConnectionOut.
// Implement a simple AIMD slow-start on the request queue size with
// currentMaxPipeline counter.
// Avoid cross-peer deadlocks from PeerCoordinator, call this outside the lock
if (!bwListener.shouldRequest(peer, 0)) {
synchronized(this) {
// Due to changes elsewhere we can let this go down to zero now
currentMaxPipeline /= 2;
}
if (_log.shouldWarn())
_log.warn(peer + " throttle request, interesting? " + interesting + " choked? " + choked +
" reqq: " + outstandingRequests.size() + " maxp: " + currentMaxPipeline);
return;
}
synchronized(this) {
// adjust currentMaxPipeline
long rate = bwListener.getDownloadRate();
long limit = bwListener.getDownBWLimit();
if (rate < limit * 7 / 10) {
if (currentMaxPipeline < peer.getMaxPipeline())
currentMaxPipeline++;
} else if (rate > limit * 9 / 10) {
currentMaxPipeline = 1;
} else if (currentMaxPipeline < 2) {
currentMaxPipeline++;
}
boolean more_pieces = true;
while (more_pieces)
{
more_pieces = outstandingRequests.size() < currentMaxPipeline;
// We want something and we don't have outstanding requests?
if (more_pieces && lastRequest == null) {
// we have nothing in the queue right now
if (!interesting) {
// If we need something, set interesting but delay pulling
// a request from the PeerCoordinator until unchoked.
if (listener.needPiece(this.peer, bitfield)) {
setInteresting(true);
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we need something, setting interesting, delaying requestNextPiece()");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() needs nothing");
}
return;
}
if (choked) {
// If choked, delay pulling
// a request from the PeerCoordinator until unchoked.
boolean more_pieces = true;
while (more_pieces)
{
more_pieces = outstandingRequests.size() < peer.getMaxPipeline();
// We want something and we don't have outstanding requests?
if (more_pieces && lastRequest == null) {
// we have nothing in the queue right now
if (!interesting) {
// If we need something, set interesting but delay pulling
// a request from the PeerCoordinator until unchoked.
if (listener.needPiece(this.peer, bitfield)) {
setInteresting(true);
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we are choked, delaying requestNextPiece()");
return;
_log.debug(peer + " addRequest() we need something, setting interesting, delaying requestNextPiece()");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() needs nothing");
}
more_pieces = requestNextPiece();
} else if (more_pieces) // We want something
{
int pieceLength;
boolean isLastChunk;
pieceLength = metainfo.getPieceLength(lastRequest.getPiece());
isLastChunk = lastRequest.off + lastRequest.len == pieceLength;
return;
}
if (choked) {
// If choked, delay pulling
// a request from the PeerCoordinator until unchoked.
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " addRequest() we are choked, delaying requestNextPiece()");
return;
}
// huh? rv unused
more_pieces = requestNextPiece();
} else if (more_pieces) // We want something
{
int pieceLength;
boolean isLastChunk;
pieceLength = metainfo.getPieceLength(lastRequest.getPiece());
isLastChunk = lastRequest.off + lastRequest.len == pieceLength;
// Last part of a piece?
if (isLastChunk) {
more_pieces = requestNextPiece();
} else {
// Last part of a piece?
if (isLastChunk)
more_pieces = requestNextPiece();
else
{
PartialPiece nextPiece = lastRequest.getPartialPiece();
int nextBegin = lastRequest.off + PARTSIZE;
while (true) {
// don't rerequest chunks we already have
if (!nextPiece.hasChunk(nextBegin / PARTSIZE)) {
int maxLength = pieceLength - nextBegin;
int nextLength = maxLength > PARTSIZE ? PARTSIZE
: maxLength;
Request req = new Request(nextPiece,nextBegin, nextLength);
outstandingRequests.add(req);
if (!choked)
out.sendRequest(req);
lastRequest = req;
break;
} else {
nextBegin += PARTSIZE;
if (nextBegin >= pieceLength) {
more_pieces = requestNextPiece();
break;
}
}
}
}
int maxLength = pieceLength - nextBegin;
int nextLength = maxLength > PARTSIZE ? PARTSIZE
: maxLength;
Request req
= new Request(nextPiece,nextBegin, nextLength);
outstandingRequests.add(req);
if (!choked)
out.sendRequest(req);
lastRequest = req;
}
}
}
@ -1016,6 +972,47 @@ class PeerState implements DataLoader
pp.release();
}
}
/******* getPartialPiece() does it all now
// Note that in addition to the bitfield, PeerCoordinator uses
// its request tracking and isRequesting() to determine
// what piece to give us next.
int nextPiece = listener.wantPiece(peer, bitfield);
if (nextPiece != -1
&& (lastRequest == null || lastRequest.getPiece() != nextPiece)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " want piece " + nextPiece);
// Fail safe to make sure we are interested
// When we transition into the end game we may not be interested...
if (!interesting) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " transition to end game, setting interesting");
interesting = true;
out.sendInterest(true);
}
int piece_length = metainfo.getPieceLength(nextPiece);
//Catch a common place for OOMs esp. on 1MB pieces
byte[] bs;
try {
bs = new byte[piece_length];
} catch (OutOfMemoryError oom) {
_log.warn("Out of memory, can't request piece " + nextPiece, oom);
return false;
}
int length = Math.min(piece_length, PARTSIZE);
Request req = new Request(nextPiece, bs, 0, length);
outstandingRequests.add(req);
if (!choked)
out.sendRequest(req);
lastRequest = req;
return true;
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug(peer + " no more pieces to request");
}
*******/
}
// failsafe

View File

@ -74,8 +74,8 @@ class Request
/**
* @since 0.9.1
*/
public void read(DataInputStream din, BandwidthListener bwl) throws IOException {
piece.read(din, off, len, bwl);
public void read(DataInputStream din) throws IOException {
piece.read(din, off, len);
}
/**

View File

@ -608,7 +608,7 @@ public class Snark
if (_log.shouldLog(Log.INFO))
_log.info("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient");
activity = "Collecting pieces";
coordinator = new PeerCoordinator(_util, id, infoHash, meta, storage, this, this, completeListener.getBandwidthListener());
coordinator = new PeerCoordinator(_util, id, infoHash, meta, storage, this, this);
coordinator.setUploaded(savedUploaded);
if (_peerCoordinatorSet != null) {
// multitorrent
@ -1335,9 +1335,6 @@ public class Snark
*/
public void replaceMetaInfo(MetaInfo metainfo) {
meta = metainfo;
TrackerClient tc = trackerclient;
if (tc != null)
tc.reinitialize();
}
///////////// Begin StorageListener methods
@ -1470,6 +1467,31 @@ public class Snark
return totalUploaders > limit;
}
/**
* Is i2psnark as a whole over its limit?
*/
public boolean overUpBWLimit() {
if (_peerCoordinatorSet == null)
return false;
long total = 0;
for (PeerCoordinator c : _peerCoordinatorSet) {
if (!c.halted())
total += c.getCurrentUploadRate();
}
long limit = 1024l * _util.getMaxUpBW();
if (_log.shouldLog(Log.INFO))
_log.info("Total up bw: " + total + " Limit: " + limit);
return total > limit;
}
/**
* Is a particular peer who has this recent download rate (in Bps) over our upstream bandwidth limit?
*/
public boolean overUpBWLimit(long total) {
long limit = 1024l * _util.getMaxUpBW();
return total > limit;
}
/**
* A unique ID for this torrent, useful for RPC
* @return positive value unless you wrap around

View File

@ -25,12 +25,10 @@ import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.CoreVersion;
import net.i2p.I2PAppContext;
import net.i2p.app.ClientApp;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import net.i2p.app.NavService;
import net.i2p.app.NotificationService;
import net.i2p.client.I2PClient;
import net.i2p.client.streaming.I2PSocketManager.DisconnectListener;
@ -89,7 +87,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
private final I2PSnarkUtil _util;
private final PeerCoordinatorSet _peerCoordinatorSet;
private final ConnectionAcceptor _connectionAcceptor;
private final BandwidthManager _bwManager;
private Thread _monitor;
private volatile boolean _running;
private volatile boolean _stopping;
@ -105,8 +102,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
//public static final String PROP_EEP_PORT = "i2psnark.eepPort";
public static final String PROP_UPLOADERS_TOTAL = "i2psnark.uploaders.total";
public static final String PROP_UPBW_MAX = "i2psnark.upbw.max";
/** @since 0.9.62 */
public static final String PROP_DOWNBW_MAX = "i2psnark.downbw.max";
public static final String PROP_DIR = "i2psnark.dir";
private static final String PROP_META_PREFIX = "i2psnark.zmeta.";
private static final String PROP_META_RUNNING = "running";
@ -132,7 +127,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
private static final String PROP_META_ACTIVITY = "activity";
private static final String CONFIG_FILE_SUFFIX = ".config";
public static final String CONFIG_FILE = "i2psnark" + CONFIG_FILE_SUFFIX;
private static final String CONFIG_FILE = "i2psnark" + CONFIG_FILE_SUFFIX;
private static final String COMMENT_FILE_SUFFIX = ".comments.txt.gz";
public static final String PROP_FILES_PUBLIC = "i2psnark.filesPublic";
public static final String PROP_OLD_AUTO_START = "i2snark.autoStart"; // oops
@ -167,25 +162,17 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
private static final String PROP_COMMENTS = "i2psnark.comments";
/** @since 0.9.31 */
private static final String PROP_COMMENTS_NAME = "i2psnark.commentsName";
/** @since 0.9.58 */
public static final String PROP_MAX_FILES_PER_TORRENT = "i2psnark.maxFilesPerTorrent";
public static final int MIN_UP_BW = 10;
public static final int MIN_DOWN_BW = 2 * MIN_UP_BW;
public static final int DEFAULT_MAX_UP_BW = 25;
private static final int DEFAULT_MAX_DOWN_BW = 200;
public static final int DEFAULT_STARTUP_DELAY = 3;
public static final int DEFAULT_REFRESH_DELAY_SECS = 15;
private static final int DEFAULT_PAGE_SIZE = 50;
public static final int DEFAULT_TUNNEL_QUANTITY = 3;
public static final int DEFAULT_MAX_FILES_PER_TORRENT = 2000;
public static final String CONFIG_DIR_SUFFIX = ".d";
private static final String SUBDIR_PREFIX = "s";
private static final String B64 = Base64.ALPHABET_I2P;
private static final int MAX_MESSAGES = 100;
private static final String EXTRA = "";
/** @since 0.9.58 */
public static final String FULL_VERSION = CoreVersion.VERSION + EXTRA;
/**
* "name", "announceURL=websiteURL" pairs
@ -242,9 +229,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
// psi go - unregistered
"uajd4nctepxpac4c4bdyrdw7qvja2a5u3x25otfhkptcjgd53ioq.b32.i2p",
// Vuze - unregistered
"crs2nugpvoqygnpabqbopwyjqettwszth6ubr2fh7whstlos3a6q.b32.i2p",
"opentracker.r4sas.i2p", "punzipidirfqspstvzpj6gb4tkuykqp6quurj6e23bgxcxhdoe7q.b32.i2p",
"opentracker.skank.i2p", "by7luzwhx733fhc5ug2o75dcaunblq2ztlshzd7qvptaoa73nqua.b32.i2p"
"crs2nugpvoqygnpabqbopwyjqettwszth6ubr2fh7whstlos3a6q.b32.i2p"
}));
static {
@ -288,7 +273,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
_util = new I2PSnarkUtil(_context, ctxName, this);
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util, _peerCoordinatorSet);
_bwManager = new BandwidthManager(ctx, DEFAULT_MAX_UP_BW * 1024, DEFAULT_MAX_DOWN_BW * 1024);
DEFAULT_AUTO_START = !ctx.isRouterContext();
String cfile = ctxName + CONFIG_FILE_SUFFIX;
File configFile = new File(cfile);
@ -307,21 +291,12 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
*/
public void start() {
_running = true;
ClientAppManager cmgr = _context.clientAppManager();
if ("i2psnark".equals(_contextName)) {
// Register with the ClientAppManager so the rpc plugin can find us
// only if default instance
ClientAppManager cmgr = _context.clientAppManager();
if (cmgr != null)
cmgr.register(this);
} else {
// Register link with NavHelper
if (cmgr != null) {
NavService nav = (NavService) cmgr.getRegisteredApp("NavHelper");
if (nav != null) {
String name = DataHelper.stripHTML(_contextPath.substring(1));
nav.registerApp(name, name, _contextPath, null, "/themes/console/images/i2psnark.png");
}
}
}
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
_monitor.start();
@ -402,20 +377,11 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
_connectionAcceptor.halt();
_idleChecker.cancel();
stopAllTorrents(true);
ClientAppManager cmgr = _context.clientAppManager();
if ("i2psnark".equals(_contextName)) {
// only if default instance
ClientAppManager cmgr = _context.clientAppManager();
if (cmgr != null)
cmgr.unregister(this);
} else {
// Unregister link with NavHelper
if (cmgr != null) {
NavService nav = (NavService) cmgr.getRegisteredApp("NavHelper");
if (nav != null) {
String name = DataHelper.stripHTML(_contextPath.substring(1));
nav.unregisterApp(name);
}
}
}
if (_log.shouldWarn())
_log.warn("Snark stop() end");
@ -467,14 +433,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
/** hook to I2PSnarkUtil for the servlet */
public I2PSnarkUtil util() { return _util; }
/**
* The BandwidthManager.
* @since 0.9.62
*/
public BandwidthListener getBandwidthListener() {
return _bwManager;
}
/**
* Use if it does not include a link.
* Escapes '&lt;' and '&gt;' before queueing
@ -743,7 +701,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
File conf = configFile(_configDir, ih);
synchronized(_configLock) { // one lock for all
try {
I2PSnarkUtil.loadProps(rv, conf);
DataHelper.loadProps(rv, conf);
} catch (IOException ioe) {}
}
return rv;
@ -984,21 +942,13 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
* @return true if we got a response from the router
*/
private boolean getBWLimit() {
int[] limits = BWLimits.getBWLimits(_util.getI2CPHost(), _util.getI2CPPort());
if (limits == null)
return false;
int up = limits[1];
if (up > 0) {
int maxup = getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW);
if (maxup > up)
maxup = up;
_util.setMaxUpBW(maxup);
_bwManager.setUpBWLimit(maxup * 1000L);
}
int down = limits[0];
if (down > 0) {
int maxdown = getInt(PROP_DOWNBW_MAX, DEFAULT_MAX_DOWN_BW);
_bwManager.setDownBWLimit(Math.min(down, maxdown) * 1000L);
boolean shouldSet = !_config.containsKey(PROP_UPBW_MAX);
if (shouldSet || !_context.isRouterContext()) {
int[] limits = BWLimits.getBWLimits(_util.getI2CPHost(), _util.getI2CPPort());
if (limits == null)
return false;
if (shouldSet && limits[1] > 0)
_util.setMaxUpBW(limits[1]);
}
return true;
}
@ -1027,7 +977,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
// _util.setProxy(eepHost, eepPort);
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
_util.setMaxFilesPerTorrent(getInt(PROP_MAX_FILES_PER_TORRENT, DEFAULT_MAX_FILES_PER_TORRENT));
_util.setStartupDelay(getInt(PROP_STARTUP_DELAY, DEFAULT_STARTUP_DELAY));
_util.setFilesPublic(areFilesPublic());
_util.setOpenTrackers(getListConfig(PROP_OPENTRACKERS, DEFAULT_OPENTRACKERS));
@ -1070,13 +1019,13 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
public void updateConfig(String dataDir, boolean filesPublic, boolean autoStart, boolean smartSort, String refreshDelay,
String startDelay, String pageSize, String seedPct, String eepHost,
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
String upLimit, String upBW, String downBW, boolean useOpenTrackers, boolean useDHT, String theme,
String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme,
String lang, boolean enableRatings, boolean enableComments, String commentName, boolean collapsePanels) {
synchronized(_configLock) {
locked_updateConfig(dataDir, filesPublic, autoStart, smartSort, refreshDelay,
startDelay, pageSize, seedPct, eepHost,
eepPort, i2cpHost, i2cpPort, i2cpOpts,
upLimit, upBW, downBW, useOpenTrackers, useDHT, theme,
upLimit, upBW, useOpenTrackers, useDHT, theme,
lang, enableRatings, enableComments, commentName, collapsePanels);
}
}
@ -1084,7 +1033,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
private void locked_updateConfig(String dataDir, boolean filesPublic, boolean autoStart, boolean smartSort, String refreshDelay,
String startDelay, String pageSize, String seedPct, String eepHost,
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
String upLimit, String upBW, String downBW, boolean useOpenTrackers, boolean useDHT, String theme,
String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme,
String lang, boolean enableRatings, boolean enableComments, String commentName, boolean collapsePanels) {
boolean changed = false;
boolean interruptMonitor = false;
@ -1122,7 +1071,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
if ( limit != _util.getMaxUpBW()) {
if ( limit >= MIN_UP_BW ) {
_util.setMaxUpBW(limit);
_bwManager.setUpBWLimit(limit * 1000L);
changed = true;
_config.setProperty(PROP_UPBW_MAX, Integer.toString(limit));
addMessage(_t("Up BW limit changed to {0}KBps", limit));
@ -1131,20 +1079,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
}
}
}
if (downBW != null) {
int limit = (int) (_bwManager.getDownBWLimit() / 1024);
try { limit = Integer.parseInt(downBW.trim()); } catch (NumberFormatException nfe) {}
if ( limit != _bwManager.getDownBWLimit()) {
if ( limit >= MIN_DOWN_BW ) {
_bwManager.setDownBWLimit(limit * 1000L);
changed = true;
_config.setProperty(PROP_DOWNBW_MAX, Integer.toString(limit));
//addMessage(_t("Up BW limit changed to {0}KBps", limit));
} else {
//addMessage(_t("Minimum up bandwidth limit is {0}KBps", MIN_UP_BW));
}
}
}
if (startDelay != null && _context.isRouterContext()) {
int minutes = _util.getStartupDelay();
@ -1201,9 +1135,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
if (dataDir != null && !dataDir.equals(getDataDir().getAbsolutePath())) {
dataDir = DataHelper.stripHTML(dataDir.trim());
File dd = areFilesPublic() ? new File(dataDir) : new SecureDirectory(dataDir);
if (_util.connected()) {
addMessage(_t("Stop all torrents before changing data directory"));
} else if (!dd.isAbsolute()) {
if (!dd.isAbsolute()) {
addMessage(_t("Data directory must be an absolute path") + ": " + dataDir);
} else if (!dd.exists() && !dd.mkdirs()) {
// save this tag for now, may need it again
@ -1219,16 +1151,10 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
addMessage(_t("No write permissions for data directory") + ": " + dataDir);
changed = true;
interruptMonitor = true;
synchronized (_snarks) {
for (Snark snark : _snarks.values()) {
// leave magnets alone, remove everything else
if (snark.getMetaInfo() != null)
stopTorrent(snark, true);
}
_config.setProperty(PROP_DIR, dataDir);
}
_config.setProperty(PROP_DIR, dataDir);
addMessage(_t("Data directory changed to {0}", dataDir));
}
}
// Standalone (app context) language.
@ -1306,9 +1232,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
Properties p = new Properties();
p.putAll(opts);
_util.setI2CPConfig(i2cpHost, port, p);
int max = getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW);
_util.setMaxUpBW(max);
_bwManager.setUpBWLimit(max * 1000);
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
addMessage(_t("I2CP and tunnel changes will take effect after stopping all torrents"));
} else if (!reconnect) {
// The usual case, the other two are if not in router context
@ -1323,9 +1247,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
}
addMessage(_t("I2CP settings changed to {0}", i2cpHost + ':' + port + ' ' + i2cpOpts));
_util.setI2CPConfig(i2cpHost, port, opts);
int max = getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW);
_util.setMaxUpBW(max);
_bwManager.setUpBWLimit(max * 1000);
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
boolean ok = _util.connect();
if (!ok) {
addMessage(_t("Unable to connect with the new settings, reverting to the old I2CP settings"));
@ -1534,6 +1456,9 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
}
}
/** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */
public static final int MAX_FILES_PER_TORRENT = 2000;
/**
* Set of canonical .torrent filenames that we are dealing with.
* An unsynchronized copy.
@ -2360,7 +2285,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
if (!subdir.exists())
subdir.mkdirs();
try {
I2PSnarkUtil.storeProps(config, conf);
DataHelper.storeProps(config, conf);
if (_log.shouldInfo())
_log.info("Saved config to " + conf /* , new Exception() */ );
} catch (IOException ioe) {
@ -2502,11 +2427,8 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
*/
private String validateTorrent(MetaInfo info) {
List<List<String>> files = info.getFiles();
if (files != null && files.size() > _util.getMaxFilesPerTorrent()) {
return _t("Too many files in \"{0}\" ({1})!", info.getName(), files.size()) +
" - limit is " + _util.getMaxFilesPerTorrent() + ", zip them or set " +
PROP_MAX_FILES_PER_TORRENT + '=' + files.size() + " in " +
_configFile.getAbsolutePath() + " and restart";
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
return _t("Too many files in \"{0}\" ({1})!", info.getName(), files.size());
} else if ( (files == null) && (info.getName().endsWith(".torrent")) ) {
return _t("Torrent file \"{0}\" cannot end in \".torrent\"!", info.getName());
} else if (info.getPieces() <= 0) {
@ -2625,9 +2547,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
try { Thread.sleep(delay); } catch (InterruptedException ie) {}
// Remove that first message
_messages.clearThrough(id);
} else if (_context.isRouterContext()) {
// to wait for client manager to be up so we can get bandwidth limits
try { Thread.sleep(3000); } catch (InterruptedException ie) {}
}
// here because we need to delay until I2CP is up
@ -2695,8 +2614,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
}
}
if (routerOK)
addMessage(_t("Down bandwidth limit is {0} KBps", _bwManager.getUpBWLimit() / 1024) + "; " +
_t("Up bandwidth limit is {0} KBps", _util.getMaxUpBW()));
addMessage(_t("Up bandwidth limit is {0} KBps", _util.getMaxUpBW()));
}
} else {
autostart = false;
@ -2962,7 +2880,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("DirMon found: " + DataHelper.toString(foundNames) + " existing: " + DataHelper.toString(existingNames));
// lets find new ones first...
int count = 0;
for (String name : foundNames) {
if (existingNames.contains(name)) {
// already known. noop
@ -2990,10 +2907,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
disableTorrentFile(name);
rv = false;
}
if (shouldStart && (count++ & 0x0f) == 15) {
// try to prevent OOMs at startup
try { Thread.sleep(250); } catch (InterruptedException ie) {}
}
}
}
// Don't remove magnet torrents that don't have a torrent file yet
@ -3173,19 +3086,21 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
}
/**
* Always thread it
* If not connected, thread it, otherwise inline
* @since 0.9.1
*/
public void startAllTorrents() {
if (!_util.connected()) {
if (_util.connected()) {
startAll();
} else {
addMessage(_t("Opening the I2P tunnel and starting all torrents."));
for (Snark snark : _snarks.values()) {
// mark it for the UI
snark.setStarting();
}
(new I2PAppThread(new ThreadedStarter(null), "TorrentStarterAll", true)).start();
try { Thread.sleep(200); } catch (InterruptedException ie) {}
}
(new I2PAppThread(new ThreadedStarter(null), "TorrentStarterAll", true)).start();
try { Thread.sleep(200); } catch (InterruptedException ie) {}
}
/**
@ -3215,7 +3130,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
* @since 0.9.1
*/
private void startAll() {
int count = 0;
for (Snark snark : _snarks.values()) {
if (snark.isStopped()) {
try {
@ -3223,10 +3137,6 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
} catch (RuntimeException re) {
// Snark.fatal() will log and call fatal() here for user message before throwing
}
if ((count++ & 0x0f) == 15) {
// try to prevent OOMs
try { Thread.sleep(250); } catch (InterruptedException ie) {}
}
}
}
}
@ -3245,29 +3155,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
if (finalShutdown && _log.shouldLog(Log.WARN))
_log.warn("SnarkManager final shutdown");
int count = 0;
Collection<Snark> snarks = _snarks.values();
// We do two passes so we shutdown the high-priority snarks first.
// Pass 1: All running, incomplete torrents,
// to make sure the status gets saved so there will be no recheck on restart.
for (Snark snark : snarks) {
if (!snark.isStopped()) {
Storage storage = snark.getStorage();
if (storage != null && !storage.complete()) {
if (count == 0)
addMessage(_t("Stopping all torrents and closing the I2P tunnel."));
count++;
if (finalShutdown)
snark.stopTorrent(true);
else
stopTorrent(snark, false);
if (count % 8 == 0) {
try { Thread.sleep(20); } catch (InterruptedException ie) {}
}
}
}
}
// Pass 2: All the rest of the torrents
for (Snark snark : snarks) {
for (Snark snark : _snarks.values()) {
if (!snark.isStopped()) {
if (count == 0)
addMessage(_t("Stopping all torrents and closing the I2P tunnel."));

View File

@ -87,7 +87,7 @@ public class Storage implements Closeable
/** bigger than this will be rejected */
public static final int MAX_PIECE_SIZE = 32*1024*1024;
/** The maximum number of pieces in a torrent. */
public static final int MAX_PIECES = 64*1024;
public static final int MAX_PIECES = 32*1024;
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;
public static final int PRIORITY_SKIP = -9;
public static final int PRIORITY_NORMAL = 0;
@ -288,15 +288,9 @@ public class Storage implements Closeable
* @throws IOException if too many total files
*/
private void addFiles(List<File> l, File f) throws IOException {
int max = _util.getMaxFilesPerTorrent();
if (!f.isDirectory()) {
int sz = l.size() + 1;
if (sz > max)
throw new IOException(_util.getString("Too many files in \"{0}\" ({1})!",
(metainfo != null ? metainfo.getName() : _base.toString()), sz) +
" - limit is " + max + ", zip them or set " +
SnarkManager.PROP_MAX_FILES_PER_TORRENT + '=' + sz + " in " +
SnarkManager.CONFIG_FILE + " and restart");
if (l.size() >= SnarkManager.MAX_FILES_PER_TORRENT)
throw new IOException("Too many files, limit is " + SnarkManager.MAX_FILES_PER_TORRENT + ", zip them?");
l.add(f);
} else {
File[] files = f.listFiles();
@ -307,13 +301,6 @@ public class Storage implements Closeable
+ "' not a normal file.");
return;
}
int sz = l.size() + files.length;
if (sz > max)
throw new IOException(_util.getString("Too many files in \"{0}\" ({1})!",
(metainfo != null ? metainfo.getName() : _base.toString()), sz) +
" - limit is " + max + ", zip them or set " +
SnarkManager.PROP_MAX_FILES_PER_TORRENT + '=' + sz + " in " +
SnarkManager.CONFIG_FILE + " and restart");
for (int i = 0; i < files.length; i++)
addFiles(l, files[i]);
}
@ -913,10 +900,7 @@ public class Storage implements Closeable
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
// unicode newlines
0x2028, 0x2029,
// LTR/RTL
// https://security.stackexchange.com/questions/158802/how-can-this-executable-have-an-avi-extension
0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x200e, 0x200f
0x2028, 0x2029
};
// https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file

View File

@ -94,8 +94,7 @@ public class TrackerClient implements Runnable {
private static final Hash DSA_ONLY_TRACKER = ConvertToHash.getHash("cfmqlafjfmgkzbt4r3jsfyhgsr5abgxryl6fnz3d3y5a365di5aa.b32.i2p");
private final I2PSnarkUtil _util;
// non-final for reinitialize()
private MetaInfo meta;
private final MetaInfo meta;
private final String infoHash;
private final String peerID;
private final String additionalTrackerURL;
@ -267,22 +266,8 @@ public class TrackerClient implements Runnable {
}
}
/**
* Call after editing torrent
* @since 0.9.57
*/
public synchronized void reinitialize() {
if (!_initialized || !stop)
return;
trackers.clear();
backupTrackers.clear();
meta = snark.getMetaInfo();
setup();
}
/**
* Do this one time only (not every time it is started).
* Unless torrent was edited.
* @since 0.9.1
*/
private void setup() {

View File

@ -128,7 +128,7 @@ class UDPTrackerClient implements I2PSessionMuxedListener {
*
* @param ih the Info Hash (torrent)
* @param max maximum number of peers to return
* @param maxWait the maximum time to wait (ms) must be greater than 0
* @param maxWait the maximum time to wait (ms) must be > 0
* @param fast if true, don't wait for dest, no retx, ...
* @return null on fail or if fast is true
*/

View File

@ -319,13 +319,6 @@ class UpdateRunner implements UpdateTask, CompleteListener {
return _smgr.shouldAutoStart();
}
/**
* @since 0.9.62
*/
public BandwidthListener getBandwidthListener() {
return _smgr.getBandwidthListener();
}
//////// end CompleteListener methods
private static String linkify(String url) {

View File

@ -122,7 +122,7 @@ class WebPeer extends Peer implements EepGet.StatusListener {
* @param uploadOnly if we are complete with skipped files, i.e. a partial seed
*/
@Override
public void runConnection(I2PSnarkUtil util, PeerListener listener, BandwidthListener bwl, BitField ignore,
public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField ignore,
MagnetState mState, boolean uploadOnly) {
if (uploadOnly)
return;
@ -204,8 +204,6 @@ class WebPeer extends Peer implements EepGet.StatusListener {
if (i >= maxRequests)
break;
Request r = outstandingRequests.get(i);
if (!shouldRequest(r.len))
break;
if (r.getPiece() == piece &&
lastRequest.off + lastRequest.len == r.off) {
requests.add(r);
@ -342,7 +340,7 @@ class WebPeer extends Peer implements EepGet.StatusListener {
Request req = iter.next();
if (dis.available() < req.len)
break;
req.read(dis, this);
req.read(dis);
iter.remove();
if (_log.shouldWarn())
_log.warn("Saved chunk " + req + " recvd before failure");
@ -365,13 +363,13 @@ class WebPeer extends Peer implements EepGet.StatusListener {
_log.debug("Fetch of piece: " + piece + " chunks: " + requests.size() + " offset: " + off + " torrent offset: " + toff + " len: " + tlen + " successful");
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(out.toByteArray()));
for (Request req : requests) {
req.read(dis, this);
req.read(dis);
}
PartialPiece pp = last.getPartialPiece();
synchronized(pp) {
// Last chunk needed for this piece?
if (pp.isComplete()) {
if (pp.getLength() == pp.getDownloaded()) {
if (listener.gotPiece(this, pp)) {
if (_log.shouldDebug())
_log.debug("Got " + piece + ": " + this);
@ -521,29 +519,6 @@ class WebPeer extends Peer implements EepGet.StatusListener {
return false;
}
// begin BandwidthListener interface overrides
// Because super doesn't have a PeerState
/**
* @since 0.9.62
*/
@Override
public void downloaded(int size) {
super.downloaded(size);
_coordinator.downloaded(size);
}
/**
* Should we request this many bytes?
* @since 0.9.62
*/
@Override
public boolean shouldRequest(int size) {
return _coordinator.shouldRequest(this, size);
}
// end BandwidthListener interface overrides
// private methods below here implementing parts of PeerState
private synchronized void addRequest() {
@ -573,8 +548,7 @@ class WebPeer extends Peer implements EepGet.StatusListener {
Request req = new Request(nextPiece,nextBegin, nextLength);
outstandingRequests.add(req);
lastRequest = req;
if (shouldRequest(maxLength))
this.notifyAll();
this.notifyAll();
}
}
}
@ -593,8 +567,7 @@ class WebPeer extends Peer implements EepGet.StatusListener {
Request r = pp.getRequest();
outstandingRequests.add(r);
lastRequest = r;
if (shouldRequest(r.len))
this.notifyAll();
this.notifyAll();
return true;
} else {
if (_log.shouldLog(Log.WARN))
@ -650,8 +623,15 @@ class WebPeer extends Peer implements EepGet.StatusListener {
List<Request> rv = new ArrayList<Request>(pcs.size());
for (Integer p : pcs) {
Request req = getLowestOutstandingRequest(p.intValue());
if (req != null)
if (req != null) {
PartialPiece pp = req.getPartialPiece();
synchronized(pp) {
int dl = pp.getDownloaded();
if (req.off != dl)
req = new Request(pp, dl);
}
rv.add(req);
}
}
outstandingRequests.clear();
return rv;
@ -673,6 +653,8 @@ class WebPeer extends Peer implements EepGet.StatusListener {
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {
lastRcvd = System.currentTimeMillis();
downloaded(currentWrite);
listener.downloaded(this, currentWrite);
}
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {}

View File

@ -294,7 +294,7 @@ public class BDecoder
/**
* Returns the next bencoded value on the stream and makes sure it
* is a map (dictionary). If it is not a map it will throw
* is a map (dictonary). If it is not a map it will throw
* InvalidBEncodingException.
*/
public BEValue bdecodeMap() throws IOException
@ -311,7 +311,7 @@ public class BDecoder
c = getNextIndicator();
while (c != 'e')
{
// Dictionary keys are always strings.
// Dictonary keys are always strings.
String key = bdecode().getString();
// XXX ugly hack

View File

@ -32,7 +32,7 @@ public class Comment implements Comparable<Comment> {
public static final int MAX_NAME_LEN = 32;
// same as IRC, more or less
private static final int MAX_TEXT_LEN = 512;
private static final int BUCKET_SIZE = 4*60*60*1000;
private static final int BUCKET_SIZE = 10*60*1000;
private static final long TIME_SHRINK = 1000L;
private static final int MAX_SKEW = (int) (BUCKET_SIZE / TIME_SHRINK);
// 1/1/2005

View File

@ -100,7 +100,6 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
private final ConcurrentHashMap<NID, Token> _incomingTokens;
/** recently unreachable, with lastSeen() as the added-to-blacklist time */
private final Set<NID> _blacklist;
private SimpleTimer2.TimedEvent _cleaner, _explorer;
/** hook to inject and receive datagrams */
private final I2PSession _session;
@ -624,8 +623,6 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
public synchronized void start() {
if (_isRunning)
return;
if (_log.shouldInfo())
_log.info("KRPC start", new Exception());
_session.addMuxedSessionListener(this, I2PSession.PROTO_DATAGRAM_RAW, _rPort);
_session.addMuxedSessionListener(this, I2PSession.PROTO_DATAGRAM, _qPort);
_knownNodes.start();
@ -633,8 +630,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
PersistDHT.loadDHT(this, _dhtFile, _backupDhtFile);
// start the explore thread
_isRunning = true;
_cleaner = new Cleaner();
_explorer = new Explorer(5*1000);
// no need to keep ref, it will eventually stop
new Cleaner();
new Explorer(5*1000);
_txPkts.set(0);
_rxPkts.set(0);
_txBytes.set(0);
@ -650,10 +648,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
if (!_isRunning)
return;
_isRunning = false;
if (_log.shouldInfo())
_log.info("KRPC stop", new Exception());
_cleaner.cancel();
_explorer.cancel();
// FIXME stop the explore thread
// unregister port listeners
_session.removeListener(I2PSession.PROTO_DATAGRAM, _qPort);
_session.removeListener(I2PSession.PROTO_DATAGRAM_RAW, _rPort);
@ -688,7 +683,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
public String renderStatusHTML() {
long uptime = Math.max(1000, _context.clock().now() - _started);
StringBuilder buf = new StringBuilder(256);
buf.append("<br><hr class=\"debug\"><br><hr class=\"debug\"><hr><b>TX:</b> ").append(_txPkts.get()).append(" pkts / ")
buf.append("<br><hr class=\"debug\"><b>DHT DEBUG</b><br><hr class=\"debug\"><hr><b>TX:</b> ").append(_txPkts.get()).append(" pkts / ")
.append(DataHelper.formatSize2(_txBytes.get())).append("B / ")
.append(DataHelper.formatSize2Decimal(_txBytes.get() * 1000 / uptime)).append("Bps<br>" +
"<b>RX:</b> ").append(_rxPkts.get()).append(" pkts / ")
@ -1645,7 +1640,6 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
public void disconnected(I2PSession session) {
if (_log.shouldLog(Log.WARN))
_log.warn("KRPC disconnected");
stop();
}
public void errorOccurred(I2PSession session, String message, Throwable error) {
@ -1766,7 +1760,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
}
if (_log.shouldLog(Log.INFO))
_log.info("Explore of " + keys.size() + " buckets done, new size: " + _knownNodes.size());
_explorer = new Explorer(EXPLORE_TIME);
new Explorer(EXPLORE_TIME);
}
}
}

View File

@ -31,13 +31,12 @@ public class ConfigUIHelper {
{ "az", "az", "Azerbaijani", null },
{ "cs", "cz", "Čeština", null },
{ "zh", "cn", "Chinese 中文", null },
{ "zh_TW", "tw", "Chinese 中文", "Taiwan" },
//{ "zh_TW", "tw", "Chinese 中文", "Taiwan" },
{ "da", "dk", "Dansk", null },
{ "de", "de", "Deutsch", null },
//{ "et", "ee", "Eesti", null },
{ "en", "us", "English", null },
{ "es", "es", "Español", null },
{ "es_AR", "ar", "Español" ,"Argentina" },
{ "fa", "ir", "Persian فارسی", null },
{ "fr", "fr", "Français", null },
//{ "gl", "lang_gl", "Galego", null },

View File

@ -8,19 +8,13 @@ import java.util.Properties;
import org.eclipse.jetty.util.log.Log;
import net.i2p.I2PAppContext;
import net.i2p.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.app.MenuService;
import net.i2p.apps.systray.UrlLauncher;
import net.i2p.data.DataHelper;
import net.i2p.desktopgui.ExternalMain;
import net.i2p.jetty.I2PLogger;
import net.i2p.jetty.JettyStart;
import net.i2p.util.I2PAppThread;
import net.i2p.util.SystemVersion;
import org.klomp.snark.SnarkManager;
/**
* @since moved from ../web and fixed in 0.9.27
*/
@ -77,19 +71,14 @@ public class RunStandalone {
public void start() {
try {
String url = "http://" + _host + ':' + _port + "/i2psnark/";
System.out.println("Starting i2psnark " + SnarkManager.FULL_VERSION + " at " + url);
MenuService dtg = startTrayApp();
System.out.println("Starting i2psnark at " + url);
startTrayApp();
_jettyStart.startup();
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {}
String p = _context.getProperty("routerconsole.browser");
if (!("/bin/false".equals(p) || "NUL".equals(p))) {
UrlLauncher launch = new UrlLauncher(_context, null, new String[] { url } );
launch.startup();
}
if (dtg != null)
dtg.addMenu("Shutdown I2PSnark", new StandaloneStopper(dtg));
UrlLauncher launch = new UrlLauncher(_context, null, new String[] { url } );
launch.startup();
} catch (Exception e) {
e.printStackTrace();
}
@ -132,47 +121,16 @@ public class RunStandalone {
/**
* @since 0.9.54 adapted from RouterConsoleRunner
* @return null on failure
*/
private MenuService startTrayApp() {
private void startTrayApp() {
try {
if (isSystrayEnabled(_context)) {
System.setProperty("java.awt.headless", "false");
ExternalMain dtg = new ExternalMain(_context, _context.clientAppManager(), null);
dtg.startup();
return dtg;
}
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
/**
* Callback when shutdown is clicked in systray
* @since 0.9.61
*/
public static class StandaloneStopper implements MenuCallback {
private final MenuService _ms;
public StandaloneStopper(MenuService ms) { _ms = ms; }
public void clicked(MenuHandle menu) {
_ms.disableMenu(menu);
_ms.updateMenu("I2PSnark shutting down", menu);
Thread t = new I2PAppThread(new StopperThread(), "Snark Stopper", true);
t.start();
}
}
/**
* Threaded shutdown
* @since 0.9.61
*/
public static class StopperThread implements Runnable {
public void run() {
shutdown();
}
}
}

View File

@ -395,11 +395,11 @@ class BasicServlet extends HttpServlet
String rtype = response.getContentType();
String ctype = content.getContentType();
if (rtype != null) {
if (rtype.contains("javascript"))
if (rtype.equals("application/javascript"))
response.setCharacterEncoding("ISO-8859-1");
} else if (ctype != null) {
response.setContentType(ctype);
if (ctype.contains("javascript"))
if (ctype.equals("application/javascript"))
response.setCharacterEncoding("ISO-8859-1");
}
response.setHeader("X-Content-Type-Options", "nosniff");
@ -586,17 +586,6 @@ class BasicServlet extends HttpServlet
protected static String addPaths(String base, String path) {
if (path == null)
return base;
if (path.equals("/")) {
// Java 17 and below:
// (new File("foo", "/")).toString() = "foo/"
// (new File("foo/", "/")).toString() = "foo/"
// Java 21:
// (new File("foo", "/")).toString() = "foo"
// (new File("foo/", "/")).toString() = "foo"
if (base.endsWith("/"))
return base;
return base + path;
}
String rv = (new File(base, path)).toString();
if (SystemVersion.isWindows())
rv = rv.replace("\\", "/");

View File

@ -3,7 +3,6 @@ package org.klomp.snark.web;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
@ -38,7 +37,6 @@ import net.i2p.data.Base32;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.servlet.RequestWrapper;
import net.i2p.servlet.util.ServletUtil;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
@ -48,7 +46,6 @@ import net.i2p.util.SystemVersion;
import net.i2p.util.Translate;
import net.i2p.util.UIMessages;
import org.klomp.snark.BandwidthListener;
import org.klomp.snark.I2PSnarkUtil;
import org.klomp.snark.MagnetURI;
import org.klomp.snark.MetaInfo;
@ -60,8 +57,6 @@ import org.klomp.snark.Storage;
import org.klomp.snark.Tracker;
import org.klomp.snark.TrackerClient;
import org.klomp.snark.URIUtil;
import org.klomp.snark.bencode.BEValue;
import org.klomp.snark.bencode.InvalidBEncodingException;
import org.klomp.snark.dht.DHT;
import org.klomp.snark.comments.Comment;
import org.klomp.snark.comments.CommentSet;
@ -217,7 +212,7 @@ public class I2PSnarkServlet extends BasicServlet {
req.setCharacterEncoding("UTF-8");
String pOverride = _manager.util().connected() ? null : "";
String peerString = getQueryString(req, pOverride, null, null, "");
String peerString = getQueryString(req, pOverride, null, null);
String cspNonce = Integer.toHexString(_context.random().nextInt());
// AJAX for mainsection
@ -329,8 +324,7 @@ public class I2PSnarkServlet extends BasicServlet {
out.write("<script src=\".resources/js/configui.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n");
} else {
delay = _manager.getRefreshDelaySeconds();
// init for search even if refresh disabled
//if (delay > 0) {
if (delay > 0) {
String jsPfx = _context.isRouterContext() ? "" : ".resources";
String downMsg = _context.isRouterContext() ? _t("Router is down") : _t("I2PSnark has stopped");
// fallback to metarefresh when javascript is disabled
@ -341,16 +335,13 @@ public class I2PSnarkServlet extends BasicServlet {
"var ajaxDelay = " + (delay * 1000) + ";\n" +
"</script>\n" +
"<script src=\".resources/js/initajax.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n");
//}
}
out.write("<script nonce=\"" + cspNonce + "\" type=\"text/javascript\">\n" +
"var deleteMessage1 = \"" + _t("Are you sure you want to delete the file \\''{0}\\'' (downloaded data will not be deleted) ?") + "\";\n" +
"var deleteMessage2 = \"" + _t("Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?") + "\";\n" +
"</script>\n" +
"<script src=\".resources/js/delete.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n" +
"<script src=\".resources/js/search.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n" +
"<script src=\".resources/js/dnd.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n");
"<script src=\".resources/js/delete.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n");
}
out.write("<script src=\"/js/iframeResizer.contentWindow.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n");
out.write(HEADER_A + _themePath + HEADER_B);
// ...and inject CSS to display panels uncollapsed
@ -373,7 +364,7 @@ public class I2PSnarkServlet extends BasicServlet {
else
out.write(_contextName);
if (!_context.isRouterContext()) {
out.write(' ' + SnarkManager.FULL_VERSION);
out.write(' ' + CoreVersion.VERSION);
}
out.write("</a>");
List<Tracker> sortedTrackers = null;
@ -385,30 +376,15 @@ public class I2PSnarkServlet extends BasicServlet {
continue;
if (_manager.util().isKnownOpenTracker(t.announceURL))
continue;
out.write(" <a href=\"" + t.baseURL + "\" class=\"snarkNav nav_tracker\" target=\"_blank\">" + t.name + "</a>\n");
out.write(" <a href=\"" + t.baseURL + "\" class=\"snarkNav nav_tracker\" target=\"_blank\">" + t.name + "</a>");
}
}
}
// end snarkNavBar
out.write("</div>\n");
if (!isConfigure) {
String search = req.getParameter("nf_s");
if (_manager.getTorrents().size() > 1 || (search != null && search.length() > 0)) {
out.write("<form class=\"search\" id = \"search\" action=\"" + _contextPath + "\" method=\"GET\">" +
"<input type=\"text\" name=\"nf_s\" size=\"20\" class=\"search\" id=\"searchbox\"");
if (search != null)
out.write(" value=\"" + DataHelper.escapeHTML(search) + '"');
out.write(">" +
"<a class=\"cancel\" id=\"searchcancel\" href=\"" + _contextPath + "/\"></a>" +
"</form>\n");
}
}
String newURL = req.getParameter("newURL");
if (newURL != null && newURL.trim().length() > 0 && req.getMethod().equals("GET"))
_manager.addMessage(_t("Click \"Add torrent\" button to fetch torrent"));
out.write("<div id=\"page\" class=\"page\"><div id=\"mainsection\" class=\"mainsection\">");
out.write("<div class=\"page\"><div id=\"mainsection\" class=\"mainsection\">");
writeMessages(out, isConfigure, peerString);
@ -510,17 +486,6 @@ public class I2PSnarkServlet extends BasicServlet {
boolean isDegraded = ua != null && ServletUtil.isTextBrowser(ua);
boolean noThinsp = isDegraded || (ua != null && ua.startsWith("Opera"));
// search
boolean isSearch = false;
String search = req.getParameter("nf_s");
if (search != null && search.length() > 0) {
List<Snark> matches = search(search, snarks);
if (matches != null) {
snarks = matches;
isSearch = true;
}
}
// pages
int start = 0;
int total = snarks.size();
@ -776,8 +741,6 @@ public class I2PSnarkServlet extends BasicServlet {
out.write(_t("Unreadable") + ": " + DataHelper.escapeHTML(dd.toString()));
} else if (!canWrite) {
out.write(_t("No write permissions for data directory") + ": " + DataHelper.escapeHTML(dd.toString()));
} else if (isSearch) {
out.write(_t("No torrents found."));
} else {
out.write(_t("No torrents loaded."));
}
@ -838,7 +801,6 @@ public class I2PSnarkServlet extends BasicServlet {
out.write(' ');
out.write(_t("Dht Debug"));
out.write("</label><div id=\"dhtDebugInner\">");
out.write(_manager.getBandwidthListener().toString());
out.write(dht.renderStatusHTML());
out.write("</div></div></th>");
}
@ -853,48 +815,6 @@ public class I2PSnarkServlet extends BasicServlet {
return start == 0;
}
/**
* search torrents for matching terms
*
* @param search non-null and %-encoded, will be decoded here
* @param snarks unmodified, order will be honored
* @return null if not a valid search, or matching torrents in same order, possibly empty
* @since 0.9.58
*/
private static List<Snark> search(String search, Collection<Snark> snarks) {
try {
search = decodePath(search);
} catch (IOException ioe) {
return null;
}
List<String> searchList = null;
String[] terms = DataHelper.split(search, " ");
for (int i = 0; i < terms.length; i++) {
String term = terms[i];
if (term.length() > 0) {
if (searchList == null)
searchList = new ArrayList<String>(4);
searchList.add(term.toLowerCase(Locale.US));
}
}
if (searchList == null)
return null;
List<Snark> matches = new ArrayList<Snark>(32);
for (Snark snark : snarks) {
String lcname = snark.getBaseName().toLowerCase(Locale.US);
// search for any term (OR)
for (int j = 0; j < searchList.size(); j++) {
String term = searchList.get(j);
if (lcname.contains(term)) {
matches.add(snark);
break;
}
}
}
return matches;
}
/**
* hidden inputs for nonce and paramters p, st, and sort
*
@ -936,19 +856,11 @@ public class I2PSnarkServlet extends BasicServlet {
if (action != null) {
buf.append("<input type=\"hidden\" name=\"action\" value=\"")
.append(action).append("\" >\n");
} else {
// for buttons, keep the search term
String sParam = req.getParameter("nf_s");
if (sParam != null) {
buf.append("<input type=\"hidden\" name=\"nf_s\" value=\"")
.append(DataHelper.escapeHTML(sParam)).append("\" >\n");
}
}
}
/**
* Build HTML-escaped and stripped query string.
* Keeps any existing search param.
* Build HTML-escaped and stripped query string
*
* @param p override or "" for default or null to keep the same as in req
* @param st override or "" for default or null to keep the same as in req
@ -957,14 +869,6 @@ public class I2PSnarkServlet extends BasicServlet {
* @since 0.9.16
*/
private static String getQueryString(HttpServletRequest req, String p, String st, String so) {
return getQueryString(req, p, st, so, null);
}
/**
* @param s search param override or "" for default or null to keep the same as in req
* @since 0.9.58
*/
private static String getQueryString(HttpServletRequest req, String p, String st, String so, String s) {
StringBuilder buf = new StringBuilder(64);
if (p == null) {
p = req.getParameter("p");
@ -997,18 +901,6 @@ public class I2PSnarkServlet extends BasicServlet {
buf.append("&amp;st=");
buf.append(st);
}
if (s == null) {
s = req.getParameter("nf_s");
if (s != null)
s = DataHelper.escapeHTML(s);
}
if (s != null && !s.equals("")) {
if (buf.length() <= 0)
buf.append("?nf_s=");
else
buf.append("&amp;nf_s=");
buf.append(s);
}
return buf.toString();
}
@ -1113,87 +1005,44 @@ public class I2PSnarkServlet extends BasicServlet {
// return;
//}
if ("Add".equals(action)) {
File dd = _manager.getDataDir();
if (!dd.canWrite()) {
_manager.addMessage(_t("No write permissions for data directory") + ": " + dd);
return;
String newURL = req.getParameter("nofilter_newURL");
/******
// NOTE - newFile currently disabled in HTML form - see below
File f = null;
if ( (newFile != null) && (newFile.trim().length() > 0) )
f = new File(newFile.trim());
if ( (f != null) && (!f.exists()) ) {
_manager.addMessage(_t("Torrent file {0} does not exist", newFile));
}
String contentType = req.getContentType();
RequestWrapper reqw = new RequestWrapper(req);
String newURL = reqw.getParameter("nofilter_newURL");
String newFile = reqw.getFilename("newFile");
if (newFile != null && newFile.trim().length() > 0) {
if (!newFile.endsWith(".torrent"))
newFile += ".torrent";
File local = new File(dd, newFile);
String newFile2 = Storage.filterName(newFile);
File local2;
if (!newFile.equals(newFile2)) {
local2 = new File(dd, newFile2);
} else {
local2 = null;
}
if (local.exists() || (local2 != null && local2.exists())) {
try {
String canonical = local.getCanonicalPath();
String canonical2 = local2 != null ? local2.getCanonicalPath() : null;
if (_manager.getTorrent(canonical) != null ||
(canonical2 != null && _manager.getTorrent(canonical2) != null))
_manager.addMessage(_t("Torrent already running: {0}", canonical));
else
_manager.addMessage(_t("Torrent already in the queue: {0}", canonical));
} catch (IOException ioe) {}
} else {
File tmp = new File(_manager.util().getTempDir(), "newTorrent-" + _manager.util().getContext().random().nextLong() + ".torrent");
InputStream in = null;
OutputStream out = null;
try {
in = reqw.getInputStream("newFile");
out = new SecureFileOutputStream(tmp);
DataHelper.copy(in, out);
out.close();
out = null;
in.close();
// test that it's a valid torrent file, and get the hash to check for dups
in = new FileInputStream(tmp);
byte[] fileInfoHash = new byte[20];
String name = MetaInfo.getNameAndInfoHash(in, fileInfoHash);
try { in.close(); } catch (IOException ioe) {}
Snark snark = _manager.getTorrentByInfoHash(fileInfoHash);
if (snark != null) {
_manager.addMessage(_t("Torrent with this info hash is already running: {0}", snark.getBaseName()));
return;
}
if (local2 != null)
local = local2;
String canonical = local.getCanonicalPath();
// This may take a LONG time to create the storage.
boolean ok = _manager.copyAndAddTorrent(tmp, canonical, dd);
if (!ok)
throw new IOException("Unknown error - check logs");
snark = _manager.getTorrentByInfoHash(fileInfoHash);
if (snark != null)
snark.startTorrent();
if ( (f != null) && (f.exists()) ) {
// NOTE - All this is disabled - load from local file disabled
File local = new File(_manager.getDataDir(), f.getName());
String canonical = null;
try {
canonical = local.getCanonicalPath();
if (local.exists()) {
if (_manager.getTorrent(canonical) != null)
_manager.addMessage(_t("Torrent already running: {0}", newFile));
else
throw new IOException("Not found: " + canonical);
} catch (IOException ioe) {
_manager.addMessageNoEscape(_t("Torrent at {0} was not valid", DataHelper.escapeHTML(newFile)) + ": " + DataHelper.stripHTML(ioe.getMessage()));
tmp.delete();
local.delete();
if (local2 != null)
local2.delete();
return;
} catch (OutOfMemoryError oom) {
_manager.addMessageNoEscape(_t("ERROR - Out of memory, cannot create torrent from {0}", DataHelper.escapeHTML(newFile)) + ": " + DataHelper.stripHTML(oom.getMessage()));
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
if (out != null) try { out.close(); } catch (IOException ioe) {}
tmp.delete();
_manager.addMessage(_t("Torrent already in the queue: {0}", newFile));
} else {
boolean ok = FileUtil.copy(f.getAbsolutePath(), local.getAbsolutePath(), true);
if (ok) {
_manager.addMessage(_t("Copying torrent to {0}", local.getAbsolutePath()));
_manager.addTorrent(canonical);
} else {
_manager.addMessage(_t("Unable to copy the torrent to {0}", local.getAbsolutePath()) + ' ' + _t("from {0}", f.getAbsolutePath()));
}
}
} catch (IOException ioe) {
_log.warn("hrm: " + local, ioe);
}
} else if (newURL != null && newURL.trim().length() > 0) {
} else
*****/
if (newURL != null) {
newURL = newURL.trim();
String newDir = reqw.getParameter("nofilter_newDir");
String newDir = req.getParameter("nofilter_newDir");
File dir = null;
if (newDir != null) {
newDir = newDir.trim();
@ -1221,6 +1070,11 @@ public class I2PSnarkServlet extends BasicServlet {
}
}
}
File dd = _manager.getDataDir();
if (!dd.canWrite()) {
_manager.addMessage(_t("No write permissions for data directory") + ": " + dd);
return;
}
if (newURL.startsWith("http://") || newURL.startsWith("https://")) {
if (isI2PTracker(newURL)) {
FetchAndAdd fetch = new FetchAndAdd(_context, _manager, newURL, dir);
@ -1284,7 +1138,7 @@ public class I2PSnarkServlet extends BasicServlet {
boolean ok = _manager.copyAndAddTorrent(file, canonical, dd);
if (!ok)
throw new IOException("Unknown error - check logs");
snark = _manager.getTorrentByInfoHash(fileInfoHash);
snark = _manager.getTorrentByBaseName(originalName);
if (snark != null)
snark.startTorrent();
else
@ -1304,7 +1158,6 @@ public class I2PSnarkServlet extends BasicServlet {
}
} else {
// no file or URL specified
_manager.addMessage(_t("Enter URL or select torrent file"));
}
} else if (action.startsWith("Stop_")) {
String torrent = action.substring(5);
@ -1456,7 +1309,6 @@ public class I2PSnarkServlet extends BasicServlet {
String i2cpOpts = buildI2CPOpts(req);
String upLimit = req.getParameter("upLimit");
String upBW = req.getParameter("upBW");
String downBW = req.getParameter("downBW");
String refreshDel = req.getParameter("refreshDelay");
String startupDel = req.getParameter("startupDelay");
String pageSize = req.getParameter("pageSize");
@ -1472,7 +1324,7 @@ public class I2PSnarkServlet extends BasicServlet {
boolean collapsePanels = req.getParameter("collapsePanels") != null;
_manager.updateConfig(dataDir, filesPublic, autoStart, smartSort, refreshDel, startupDel, pageSize,
seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts,
upLimit, upBW, downBW, useOpenTrackers, useDHT, theme,
upLimit, upBW, useOpenTrackers, useDHT, theme,
lang, ratings, comments, commentsName, collapsePanels);
// update servlet
try {
@ -1485,9 +1337,6 @@ public class I2PSnarkServlet extends BasicServlet {
} else if ("Create".equals(action)) {
String baseData = req.getParameter("nofilter_baseFile");
if (baseData != null && baseData.trim().length() > 0) {
// drag and drop, no js
if (baseData.startsWith("file://"))
baseData = baseData.substring(7);
File baseFile = new File(baseData.trim());
if (!baseFile.isAbsolute())
baseFile = new File(_manager.getDataDir(), baseData);
@ -1606,36 +1455,8 @@ public class I2PSnarkServlet extends BasicServlet {
_manager.addMessage(_t("Error creating torrent - you must enter a file or directory"));
}
} else if ("StopAll".equals(action)) {
String search = req.getParameter("nf_s");
if (search != null && search.length() > 0) {
List<Snark> matches = search(search, _manager.getTorrents());
if (matches != null) {
for (Snark snark : matches) {
_manager.stopTorrent(snark, false);
}
return;
}
}
_manager.stopAllTorrents(false);
} else if ("StartAll".equals(action)) {
String search = req.getParameter("nf_s");
if (search != null && search.length() > 0) {
List<Snark> matches = search(search, _manager.getTorrents());
if (matches != null) {
// TODO thread it
int count = 0;
for (Snark snark : matches) {
if (!snark.isStopped())
continue;
_manager.startTorrent(snark);
if ((count++ & 0x0f) == 15) {
// try to prevent OOMs
try { Thread.sleep(250); } catch (InterruptedException ie) {}
}
}
return;
}
}
_manager.startAllTorrents();
} else if ("Clear".equals(action)) {
String sid = req.getParameter("id");
@ -1941,7 +1762,7 @@ public class I2PSnarkServlet extends BasicServlet {
":</b> " + curPeers + thinsp(noThinsp) +
ngettext("1 peer", "{0} peers", knownPeers);
} else if (isRunning && curPeers > 0 && !showPeers) {
statusString = toThemeImg("stalled", "", _t("Stalled") + " (" + ngettext("Connected to {0} peer", "Connected to {0} peers", curPeers) + ")") + "</td>" +
statusString = toThemeImg("stalled", "", _t("Stalled") + " (" + ngettext("Connected to {0} peer", "Connected to {0} peers", curPeers)) + "</td>" +
"<td class=\"snarkTorrentStatus\"><b>" + _t("Stalled") +
":</b> <a href=\"" + uri + getQueryString(req, b64, null, null) + '#' + b64Short + "\">" +
curPeers + thinsp(noThinsp) +
@ -2183,73 +2004,30 @@ public class I2PSnarkServlet extends BasicServlet {
if (ch.startsWith("WebSeed@")) {
out.write(ch);
} else {
// most clients start -xx, see
// BT spec or libtorrent identify_client.cpp
// Base64 encode -xx
// Anything starting with L is -xx and has an Az version
// snark is 9 nulls followed by 3 3 3 (binary), see Snark
// PeerID.toString() skips nulls
// Base64 encode '\3\3\3' = AwMD
boolean addVersion = true;
ch = ch.substring(0, 4);
String client;
if ("AwMD".equals(ch))
client = _t("I2PSnark");
else if ("LUJJ".equals(ch))
client = "BiglyBT";
client = "BiglyBT" + getAzVersion(pid.getID());
else if ("LUFa".equals(ch))
client = "Vuze";
client = "Vuze" + getAzVersion(pid.getID());
else if ("LVhE".equals(ch))
client = "XD";
else if (ch.startsWith("LV")) // LVCS 1.0.2?; LVRS 1.0.4
client = "Transmission";
else if ("LUtU".equals(ch))
client = "KTorrent";
// libtorrent and downstreams
// https://www.libtorrent.org/projects.html
else if ("LURF".equals(ch)) // DL
client = "Deluge";
else if ("LXFC".equals(ch)) // qB
client = "qBittorrent";
else if ("LUxU".equals(ch)) // LT
client = "libtorrent";
// ancient below here
client = "XD" + getAzVersion(pid.getID());
else if ("ZV".equals(ch.substring(2,4)) || "VUZP".equals(ch))
client = "Robert" + getRobtVersion(pid.getID());
else if (ch.startsWith("LV")) // LVCS 1.0.2?; LVRS 1.0.4
client = "Transmission" + getAzVersion(pid.getID());
else if ("LUtU".equals(ch))
client = "KTorrent" + getAzVersion(pid.getID());
else if ("CwsL".equals(ch))
client = "I2PSnarkXL";
else if ("BFJT".equals(ch))
client = "I2PRufus";
else if ("TTMt".equals(ch))
client = "I2P-BT";
else {
// get client + version from handshake
client = null;
Map<String, BEValue> handshake = peer.getHandshakeMap();
if (handshake != null) {
BEValue bev = handshake.get("v");
if (bev != null) {
try {
String s = bev.getString();
if (s.length() > 0) {
if (s.length() > 64)
s = s.substring(0, 64);
client = DataHelper.escapeHTML(s);
addVersion = false;
}
} catch (InvalidBEncodingException ibee) {}
}
}
if (client == null)
client = _t("Unknown") + " (" + ch + ')';
}
if (addVersion) {
byte[] id = pid.getID();
if (id != null && id[0] == '-')
client += getAzVersion(id);
}
else
client = _t("Unknown") + " (" + ch + ')';
out.write(client + "&nbsp;<tt title=\"");
out.write(_t("Destination (identity) of peer"));
out.write("\">" + peer.toString().substring(5, 9)+ "</tt>");
@ -2513,9 +2291,12 @@ public class I2PSnarkServlet extends BasicServlet {
newURL = "";
else
newURL = DataHelper.stripHTML(newURL); // XSS
//String newFile = req.getParameter("newFile");
//if ( (newFile == null) || (newFile.trim().length() <= 0) ) newFile = "";
out.write("<div id=\"add\" class=\"snarkNewTorrent\">\n" +
"<form action=\"_post\" method=\"POST\" enctype=\"multipart/form-data\" accept-charset=\"UTF-8\">\n");
// *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
"<form action=\"_post\" method=\"POST\">\n");
writeHiddenInputs(out, req, "Add");
out.write("<div class=\"addtorrentsection\">" +
"<input class=\"toggle_input\" id=\"toggle_addtorrent\" type=\"checkbox\"");
@ -2531,20 +2312,19 @@ public class I2PSnarkServlet extends BasicServlet {
out.write("<hr>\n<table border=\"0\"><tr><td>");
out.write(_t("From URL"));
out.write(":<td><input type=\"text\" id=\"nofilter_newURL\" name=\"nofilter_newURL\" size=\"85\" value=\"" + newURL + "\" spellcheck=\"false\"" +
out.write(":<td><input type=\"text\" name=\"nofilter_newURL\" size=\"85\" value=\"" + newURL + "\" spellcheck=\"false\"" +
" title=\"");
out.write(_t("Enter the torrent file download URL (I2P only), magnet link, or info hash"));
out.write("\">\n");
out.write("<input type=\"submit\" id=\"addButton\" class=\"add\" value=\"");
// not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>");
out.write("<input type=\"submit\" class=\"add\" value=\"");
out.write(_t("Add torrent"));
out.write("\" name=\"foo\" ><br>\n" +
"<tr><td>");
out.write(_t("Torrent file"));
out.write(":<td><input type=\"file\" name=\"newFile\" id=\"newFile\" accept=\".torrent\"/>\n" +
"<tr><td>");
out.write(_t("Data dir"));
out.write(":<td><input type=\"text\" id=\"nofilter_newDir\" name=\"nofilter_newDir\" size=\"85\" value=\"\" spellcheck=\"false\"" +
out.write(":<td><input type=\"text\" name=\"nofilter_newDir\" size=\"85\" value=\"\" spellcheck=\"false\"" +
" title=\"");
out.write(_t("Enter the directory to save the data in (default {0})", _manager.getDataDir().getAbsolutePath()));
out.write("\"></td></tr>\n");
@ -2570,11 +2350,11 @@ public class I2PSnarkServlet extends BasicServlet {
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
out.write(_t("Data to seed"));
out.write(":<td>"
+ "<input type=\"text\" id=\"nofilter_baseFile\" name=\"nofilter_baseFile\" size=\"85\" value=\""
+ "<input type=\"text\" name=\"nofilter_baseFile\" size=\"85\" value=\""
+ "\" spellcheck=\"false\" title=\"");
out.write(_t("File or directory to seed (full path or within the directory {0} )",
_manager.getDataDir().getAbsolutePath() + File.separatorChar));
out.write("\" > <input type=\"submit\" id=\"createButton\" class=\"create\" value=\"");
out.write("\" > <input type=\"submit\" class=\"create\" value=\"");
out.write(_t("Create torrent"));
out.write("\" name=\"foo\" >" +
"<tr><td>\n");
@ -2831,7 +2611,7 @@ public class I2PSnarkServlet extends BasicServlet {
out.write(":<td><input type=\"text\" name=\"upBW\" class=\"r\" value=\""
+ _manager.util().getMaxUpBW() + "\" size=\"4\" maxlength=\"4\""
+ " title=\"");
out.write(_t("Maximum bandwidth allocated"));
out.write(_t("Maximum bandwidth allocated for uploading"));
out.write("\"> KBps <td id=\"bwHelp\"><i>");
out.write(_t("Half available bandwidth recommended."));
if (_context.isRouterContext()) {
@ -2841,24 +2621,6 @@ public class I2PSnarkServlet extends BasicServlet {
out.write(_t("Configure"));
out.write("]</a>");
}
out.write("\n" +
"<tr><td>");
out.write(_t("Down bandwidth limit"));
out.write(":<td><input type=\"text\" name=\"downBW\" class=\"r\" value=\""
+ (_manager.getBandwidthListener().getDownBWLimit() / 1000) + "\" size=\"4\" maxlength=\"4\""
+ " title=\"");
out.write(_t("Maximum bandwidth allocated"));
out.write("\"> KBps <td id=\"bwHelp\"><i>");
out.write(_t("Half available bandwidth recommended."));
if (_context.isRouterContext()) {
out.write("</i> <a href=\"/config.jsp\" target=\"blank\" title=\"");
out.write(_t("View or change router bandwidth"));
out.write("\">[");
out.write(_t("Configure"));
out.write("]</a>");
}
out.write("\n<tr><td><label for=\"useOpenTrackers\">");
out.write(_t("Use open trackers also"));
out.write(":</label><td colspan=\"2\"><input type=\"checkbox\" class=\"optbox\" name=\"useOpenTrackers\" id=\"useOpenTrackers\" value=\"true\" "
@ -3193,7 +2955,7 @@ public class I2PSnarkServlet extends BasicServlet {
return escaped;
}
private static final String DOCTYPE = "<!DOCTYPE html>\n";
private static final String DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
private static final String HEADER_A = "<link id=\"pagestyle\" href=\"";
private static final String HEADER_B = "snark.css?" + CoreVersion.VERSION + "\" rel=\"stylesheet\" type=\"text/css\" >";
private static final String HEADER_C = "nocollapse.css?" + CoreVersion.VERSION + "\" rel=\"stylesheet\" type=\"text/css\" >";
@ -3412,7 +3174,7 @@ public class I2PSnarkServlet extends BasicServlet {
buf.append("</span></td></tr>");
}
List<List<String>> alist = meta.getAnnounceList();
Set<String> annlist = new TreeSet<String>();
List<String> annlist = new ArrayList<String>();
if (alist != null && !alist.isEmpty()) {
// strip non-i2p trackers
for (List<String> alist2 : alist) {
@ -4468,8 +4230,8 @@ public class I2PSnarkServlet extends BasicServlet {
if (announce != null)
annlist.add(announce);
if (!annlist.isEmpty()) {
buf.append("<tr><td colspan=\"3\"></td><td>").append(_t("Primary")).append("</td><td>")
.append(_t("Delete")).append("</td></tr>");
buf.append("<tr><td colspan=\"3\"></td><td>").append("Primary").append("</td><td>")
.append("Delete").append("</td></tr>");
for (String s : annlist) {
int hc = s.hashCode();
buf.append("<tr><td>");
@ -4501,8 +4263,8 @@ public class I2PSnarkServlet extends BasicServlet {
iter.remove();
}
if (!newTrackers.isEmpty()) {
buf.append("<tr><td colspan=\"3\"></td><td>").append(_t("Primary")).append("</td><td>")
.append(_t("Add")).append("</td></tr>");
buf.append("<tr><td colspan=\"3\"></td><td>").append("Primary").append("</td><td>")
.append("Add").append("</td></tr>");
for (Tracker t : newTrackers) {
String name = t.name;
int hc = t.announceURL.hashCode();
@ -4886,7 +4648,7 @@ public class I2PSnarkServlet extends BasicServlet {
if (newCreatedBy.equals(""))
newCreatedBy = null;
MetaInfo newMeta = new MetaInfo(thePrimary, meta.getName(), null, meta.getFiles(), meta.getLengths(),
meta.getPieceLength(0), meta.getPieceHashes(), meta.getTotalLength(), meta.getPrivateTrackerStatus(),
meta.getPieceLength(0), meta.getPieceHashes(), meta.getTotalLength(), meta.isPrivate(),
newAnnList, newCreatedBy, meta.getWebSeedURLs(), newComment);
if (!DataHelper.eq(meta.getInfoHash(), newMeta.getInfoHash())) {
// shouldn't happen

View File

@ -35,6 +35,5 @@ raiseopenfilesulimit() {
raiseopenfilesulimit
I2P="`dirname $0`"
cd "$I2P"
java $JAVA_OPTS -jar i2psnark.jar
I2P="."
java $JAVA_OPTS -jar "$I2P/i2psnark.jar"

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

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

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

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,6 @@ epub = application/epub+zip
flac = audio/flac
flv = video/x-flv
iso = application/x-iso9660-image
js = text/javascript
jxl = image/jxl
m3u = audio/mpegurl
m3u8 = audio/mpegurl

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