forked from I2P_Developers/i2p.i2p
Compare commits
1 Commits
master
...
i2p-jpacka
Author | SHA1 | Date | |
---|---|---|---|
18db2e0fbc |
@ -29,4 +29,3 @@ installer/build
|
||||
router/java/build
|
||||
router/build
|
||||
|
||||
override.properties
|
127
.github/workflows/ant-nightly.yml
vendored
127
.github/workflows/ant-nightly.yml
vendored
@ -1,127 +0,0 @@
|
||||
name: Daily Workflow
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# This runs at 00:00 UTC every day
|
||||
# Cron syntax: minute hour day-of-month month day-of-week
|
||||
- cron: '0 * * * *'
|
||||
workflow_dispatch: # Allows manual triggering
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
daily-job:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Ensures this only runs on the master branch
|
||||
if: github.ref == 'refs/heads/master'
|
||||
|
||||
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: |
|
||||
rm -f override.properties
|
||||
echo "build.built-by=GitHub Actions" >> override.properties
|
||||
echo "noExe=true" >> override.properties
|
||||
- name: build with Ant
|
||||
run: ant distclean pkg
|
||||
- name: Upload installer.jar
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: I2P-install-${{ github.sha }}.jar
|
||||
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 and place update in javadoc zip
|
||||
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 javadoc and dev build 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
|
122
.github/workflows/ant.yml
vendored
122
.github/workflows/ant.yml
vendored
@ -1,122 +0,0 @@
|
||||
# Mostly copied from https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-ant
|
||||
# zlatinb
|
||||
|
||||
name: Java CI
|
||||
|
||||
on: [push]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
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: |
|
||||
rm -f override.properties
|
||||
echo "build.built-by=GitHub Actions" >> override.properties
|
||||
echo "noExe=true" >> override.properties
|
||||
- name: build with Ant
|
||||
run: ant distclean pkg
|
||||
- name: Upload installer.jar
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: I2P-install-${{ github.sha }}.jar
|
||||
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 and place update in javadoc zip
|
||||
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 javadoc and dev build 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
|
36
.github/workflows/docker.yml
vendored
36
.github/workflows/docker.yml
vendored
@ -1,36 +0,0 @@
|
||||
name: Dockerhub
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'i2p-*.*.*'
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Set env
|
||||
run:
|
||||
sudo apt-get install -y sed;
|
||||
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" | sed 's|master|latest|g' >> $GITHUB_ENV
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
tags: geti2p/i2p:${{ env.RELEASE_VERSION }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
tags: geti2p/i2p.i2p:${{ env.RELEASE_VERSION }}
|
105
.github/workflows/izpack.yml
vendored
105
.github/workflows/izpack.yml
vendored
@ -1,105 +0,0 @@
|
||||
name: Java with IzPack Snapshot Setup
|
||||
|
||||
on: [push]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Install Required Packages
|
||||
run: sudo apt install gettext
|
||||
- name: Checkout Main Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'temurin'
|
||||
- name: Set up Maven
|
||||
uses: stCarolas/setup-maven@v4.5
|
||||
with:
|
||||
maven-version: '3.9.9'
|
||||
- name: Clone IzPack Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: 'izpack/izpack'
|
||||
path: 'izpack-source'
|
||||
- name: Build IzPack Snapshot
|
||||
working-directory: ./izpack-source
|
||||
run: |
|
||||
mvn clean install -DskipTests
|
||||
find . -iname 'izpack*.jar'
|
||||
echo "IZPACK_HOME=$GITHUB_WORKSPACE/izpack-source/izpack-dist/target/IzPack" >> $GITHUB_ENV
|
||||
echo "$GITHUB_WORKSPACE/izpack-source/izpack-dist/target/IzPack/bin" >> $GITHUB_PATH
|
||||
cat > auto-install.xml << EOF
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<AutomatedInstallation langpack="eng">
|
||||
<com.izforge.izpack.panels.HelloPanel/>
|
||||
<com.izforge.izpack.panels.TargetPanel>
|
||||
<installpath>/usr/local/IzPack</installpath>
|
||||
</com.izforge.izpack.panels.TargetPanel>
|
||||
<com.izforge.izpack.panels.InstallPanel/>
|
||||
<com.izforge.izpack.panels.FinishPanel/>
|
||||
</AutomatedInstallation>
|
||||
EOF
|
||||
|
||||
# Create installation directory
|
||||
sudo mkdir -p /usr/local/IzPack
|
||||
sudo chmod 777 /usr/local/IzPack
|
||||
|
||||
# Run the installer in headless mode
|
||||
# java -jar ./izpack-dist/target/izpack-dist-*-SNAPSHOT-installer.jar auto-install.xml
|
||||
|
||||
java -DINSTALL_PATH=/usr/local/IzPack -jar ./izpack-dist/target/izpack-dist-*-SNAPSHOT-installer.jar -options-system
|
||||
|
||||
# Update environment
|
||||
echo "/usr/local/IzPack/bin" >> $GITHUB_PATH
|
||||
echo "IZPACK_HOME=/usr/local/IzPack" >> $GITHUB_ENV
|
||||
- name: Generate Properties
|
||||
run: |
|
||||
rm -f override.properties
|
||||
echo "build.built-by=GitHub Actions" >> override.properties
|
||||
echo "izpack.home=${{ env.IZPACK_HOME }}" >> override.properties
|
||||
echo "izpack5.home=${{ env.IZPACK_HOME }}" >> override.properties
|
||||
echo "izpack5.version=5.2.4-SNAPSHOT" >> override.properties
|
||||
- name: Verify Setup
|
||||
run: |
|
||||
java -version
|
||||
ant -version
|
||||
echo "IzPack installation directory: $IZPACK_HOME"
|
||||
ls -l $IZPACK_HOME/bin
|
||||
- name: Upload IzPack Build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: izpack-snapshot-${{ github.sha }}
|
||||
path: ${{ env.IZPACK_HOME }}
|
||||
retention-days: 1
|
||||
- name: Cache IzPack Build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: izpack-source
|
||||
key: izpack-snapshot-${{ github.sha }}
|
||||
restore-keys: |
|
||||
izpack-snapshot-
|
||||
- name: build with Ant - Non Windows
|
||||
run: ant distclean pkg installer5-linux
|
||||
- name: find installer artifacts
|
||||
run: find . -iname 'i2p*.jar'
|
||||
- name: Upload i2pinstall.jar
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: i2pinstall-${{ github.sha }}.jar
|
||||
path: i2pinstall*.jar
|
||||
- name: build with Ant - Windows
|
||||
run: ant distclean pkg installer5-windows
|
||||
- name: find installer artifacts
|
||||
run: find . -iname 'i2p*.exe'
|
||||
- name: Upload i2pinstall.exe
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: i2pinstall-${{ github.sha }}.exe
|
||||
path: i2pinstall*.exe
|
66
.github/workflows/sync.yaml
vendored
66
.github/workflows/sync.yaml
vendored
@ -1,66 +0,0 @@
|
||||
# GitHub Actions workflow file to sync an external repository to this GitHub mirror.
|
||||
# This file was automatically generated by go-github-sync.
|
||||
#
|
||||
# The workflow does the following:
|
||||
# - Runs on a scheduled basis (and can also be triggered manually)
|
||||
# - Clones the GitHub mirror repository
|
||||
# - Fetches changes from the primary external repository
|
||||
# - Applies those changes to the mirror repository
|
||||
# - Pushes the updated content back to the GitHub mirror
|
||||
#
|
||||
# Authentication is handled by the GITHUB_TOKEN secret provided by GitHub Actions.
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Validate Github Actions Environment
|
||||
run: if [ "$GITHUB_ACTIONS" != "true" ]; then echo 'This script must be run in a GitHub Actions environment.'; exit 1; fi
|
||||
- name: Checkout GitHub Mirror
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Configure Git
|
||||
run: |-
|
||||
git config user.name 'GitHub Actions'
|
||||
git config user.email 'actions@github.com'
|
||||
- env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: Sync Primary Repository
|
||||
run: |-
|
||||
# Add the primary repository as a remote
|
||||
git remote add primary https://i2pgit.org/I2P_Developers/i2p.i2p.git
|
||||
|
||||
# Fetch the latest changes from the primary repository
|
||||
git fetch primary
|
||||
|
||||
# Check if the primary branch exists in the primary repository
|
||||
if git ls-remote --heads primary master | grep -q master; then
|
||||
echo "Primary branch master found in primary repository"
|
||||
else
|
||||
echo "Error: Primary branch master not found in primary repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if we're already on the mirror branch
|
||||
if git rev-parse --verify --quiet master; then
|
||||
git checkout master
|
||||
else
|
||||
# Create the mirror branch if it doesn't exist
|
||||
git checkout -b master
|
||||
fi
|
||||
|
||||
|
||||
# Force-apply all changes from primary, overriding any conflicts
|
||||
echo "Performing force sync from primary/master to master"
|
||||
git reset --hard primary/master
|
||||
|
||||
|
||||
# Push changes back to the mirror repository
|
||||
git push origin master
|
||||
name: Sync Primary Repository to GitHub Mirror
|
||||
"on":
|
||||
push: {}
|
||||
schedule:
|
||||
- cron: 0 * * * *
|
||||
workflow_dispatch: {}
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -61,5 +61,3 @@ sloccount.sc
|
||||
|
||||
# TODO: why does this file appear?
|
||||
apps/routerconsole/jsp/favicon.ico
|
||||
.tx
|
||||
/*.sh
|
@ -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"
|
||||
|
128
.tx/config
128
.tx/config
@ -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,11 +9,9 @@ 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
|
||||
trans.gan = apps/i2ptunnel/locale/messages_gan.po
|
||||
trans.hu = apps/i2ptunnel/locale/messages_hu.po
|
||||
;; Java converts id to in
|
||||
trans.id = apps/i2ptunnel/locale/messages_in.po
|
||||
@ -42,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
|
||||
@ -51,11 +43,9 @@ 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
|
||||
trans.gan = apps/i2ptunnel/locale-proxy/messages_gan.po
|
||||
trans.hu = apps/i2ptunnel/locale-proxy/messages_hu.po
|
||||
;; Java converts id to in
|
||||
trans.id = apps/i2ptunnel/locale-proxy/messages_in.po
|
||||
@ -76,10 +66,8 @@ trans.tr_TR = apps/i2ptunnel/locale-proxy/messages_tr.po
|
||||
trans.uk_UA = apps/i2ptunnel/locale-proxy/messages_uk.po
|
||||
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
|
||||
@ -94,8 +82,6 @@ trans.et_EE = core/locale/messages_et.po
|
||||
trans.fa = core/locale/messages_fa.po
|
||||
trans.fi = core/locale/messages_fi.po
|
||||
trans.fr = core/locale/messages_fr.po
|
||||
trans.gan = core/locale/messages_gan.po
|
||||
trans.hi = core/locale/messages_hi.po
|
||||
trans.hu = core/locale/messages_hu.po
|
||||
;; Java converts id to in
|
||||
trans.id = core/locale/messages_in.po
|
||||
@ -119,8 +105,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
|
||||
@ -131,13 +116,10 @@ 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
|
||||
trans.fr = router/locale/messages_fr.po
|
||||
trans.gan = router/locale/messages_gan.po
|
||||
trans.hi = router/locale/messages_hi.po
|
||||
trans.hu = router/locale/messages_hu.po
|
||||
;; Java converts id to in
|
||||
trans.id = router/locale/messages_in.po
|
||||
@ -161,8 +143,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
|
||||
@ -172,12 +153,10 @@ 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
|
||||
trans.fr = apps/routerconsole/locale/messages_fr.po
|
||||
trans.gan = apps/routerconsole/locale/messages_gan.po
|
||||
trans.hu = apps/routerconsole/locale/messages_hu.po
|
||||
;; Java converts id to in
|
||||
trans.id = apps/routerconsole/locale/messages_in.po
|
||||
@ -198,8 +177,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
|
||||
@ -208,15 +186,12 @@ 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
|
||||
trans.gan = apps/routerconsole/locale-news/messages_gan.po
|
||||
trans.gl = apps/routerconsole/locale-news/messages_gl.po
|
||||
;; Java converts he to iw
|
||||
trans.he = apps/routerconsole/locale-news/messages_iw.po
|
||||
trans.hi = apps/routerconsole/locale-news/messages_hi.po
|
||||
trans.hu = apps/routerconsole/locale-news/messages_hu.po
|
||||
;; Java converts id to in
|
||||
trans.id = apps/routerconsole/locale-news/messages_in.po
|
||||
@ -243,8 +218,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
|
||||
@ -257,7 +231,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
|
||||
@ -283,7 +256,6 @@ trans.pt_BR = apps/routerconsole/locale-countries/messages_pt_BR.po
|
||||
trans.ro = apps/routerconsole/locale-countries/messages_ro.po
|
||||
trans.ru_RU = apps/routerconsole/locale-countries/messages_ru.po
|
||||
trans.sk = apps/routerconsole/locale-countries/messages_sk.po
|
||||
trans.sl = apps/routerconsole/locale-countries/messages_sl.po
|
||||
trans.sq = apps/routerconsole/locale-countries/messages_sq.po
|
||||
trans.sr = apps/routerconsole/locale-countries/messages_sr.po
|
||||
trans.sv_SE = apps/routerconsole/locale-countries/messages_sv.po
|
||||
@ -294,21 +266,17 @@ 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
|
||||
trans.gan = apps/i2psnark/locale/messages_gan.po
|
||||
trans.hu = apps/i2psnark/locale/messages_hu.po
|
||||
;; Java converts id to in
|
||||
trans.id = apps/i2psnark/locale/messages_in.po
|
||||
@ -331,8 +299,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
|
||||
@ -341,11 +308,9 @@ 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
|
||||
trans.gan = apps/susidns/locale/messages_gan.po
|
||||
trans.gl = apps/susidns/locale/messages_gl.po
|
||||
trans.hu = apps/susidns/locale/messages_hu.po
|
||||
;; Java converts id to in
|
||||
@ -366,8 +331,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
|
||||
@ -383,9 +347,7 @@ trans.es_AR = apps/desktopgui/locale/messages_es_AR.po
|
||||
trans.fa = apps/desktopgui/locale/messages_fa.po
|
||||
trans.fi = apps/desktopgui/locale/messages_fi.po
|
||||
trans.fr = apps/desktopgui/locale/messages_fr.po
|
||||
trans.gan = apps/desktopgui/locale/messages_gan.po
|
||||
trans.gl = apps/desktopgui/locale/messages_gl.po
|
||||
trans.hi = apps/desktopgui/locale/messages_hi.po
|
||||
trans.hu = apps/desktopgui/locale/messages_hu.po
|
||||
;; Java converts id to in
|
||||
trans.id = apps/desktopgui/locale/messages_in.po
|
||||
@ -402,7 +364,6 @@ trans.pt_BR = apps/desktopgui/locale/messages_pt_BR.po
|
||||
trans.ro = apps/desktopgui/locale/messages_ro.po
|
||||
trans.ru_RU = apps/desktopgui/locale/messages_ru.po
|
||||
trans.sk = apps/desktopgui/locale/messages_sk.po
|
||||
trans.sl = apps/desktopgui/locale/messages_sl.po
|
||||
trans.sr = apps/desktopgui/locale/messages_sr.po
|
||||
trans.sv_SE = apps/desktopgui/locale/messages_sv.po
|
||||
trans.sq = apps/desktopgui/locale/messages_sq.po
|
||||
@ -413,8 +374,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
|
||||
@ -426,14 +386,10 @@ 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
|
||||
trans.gan = apps/susimail/locale/messages_gan.po
|
||||
trans.gl = apps/susimail/locale/messages_gl.po
|
||||
trans.hi = apps/susimail/locale/messages_hi.po
|
||||
trans.hr = apps/susimail/locale/messages_hr.po
|
||||
trans.hu = apps/susimail/locale/messages_hu.po
|
||||
;; Java converts he to iw
|
||||
@ -443,7 +399,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
|
||||
@ -453,7 +408,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
|
||||
@ -463,8 +417,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
|
||||
@ -473,7 +426,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
|
||||
@ -490,7 +442,6 @@ trans.pt_BR = debian/po/pt_BR.po
|
||||
trans.ro = debian/po/ro.po
|
||||
trans.ru_RU = debian/po/ru.po
|
||||
trans.sk = debian/po/sk.po
|
||||
trans.sl = debian/po/sl.po
|
||||
trans.sq = debian/po/sq.po
|
||||
trans.sv_SE = debian/po/sv.po
|
||||
trans.tk = debian/po/tk.po
|
||||
@ -499,21 +450,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.gan = installer/resources/locale/po/messages_gan.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
|
||||
@ -530,9 +476,8 @@ trans.sv_SE = installer/resources/locale/po/messages_sv.po
|
||||
trans.tr_TR = installer/resources/locale/po/messages_tr.po
|
||||
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
|
||||
@ -549,7 +494,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
|
||||
@ -558,7 +502,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
|
||||
@ -586,8 +529,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
|
||||
@ -596,18 +538,14 @@ 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
|
||||
trans.gan = apps/ministreaming/locale/messages_gan.po
|
||||
trans.gl = apps/ministreaming/locale/messages_gl.po
|
||||
trans.hi = apps/ministreaming/locale/messages_hi.po
|
||||
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
|
||||
@ -622,30 +560,24 @@ trans.tk = apps/ministreaming/locale/messages_tk.po
|
||||
trans.tr_TR = apps/ministreaming/locale/messages_tr.po
|
||||
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
|
||||
trans.ar = installer/resources/locale-man/man_ar.po
|
||||
trans.az = installer/resources/locale-man/man_az.po
|
||||
trans.cs = installer/resources/locale-man/man_cs.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.gan = installer/resources/locale-man/man_gan.po
|
||||
trans.hu = installer/resources/locale-man/man_hu.po
|
||||
trans.id = installer/resources/locale-man/man_id.po
|
||||
trans.it = installer/resources/locale-man/man_it.po
|
||||
trans.ja = installer/resources/locale-man/man_ja.po
|
||||
trans.ko = installer/resources/locale-man/man_ko.po
|
||||
trans.nl = installer/resources/locale-man/man_nl.po
|
||||
trans.pl = installer/resources/locale-man/man_pl.po
|
||||
@ -656,17 +588,13 @@ trans.ru_RU = installer/resources/locale-man/man_ru.po
|
||||
trans.sv_SE = installer/resources/locale-man/man_sv.po
|
||||
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
|
||||
;;
|
||||
;; If gan, zh, or zh_TW are updated, restore the eepsite_zh.css line
|
||||
;;
|
||||
file_filter = installer/resources/eepsite/docroot/help/index_<lang>.po
|
||||
type = HTML
|
||||
source_file = installer/resources/eepsite/docroot/help/index.html
|
||||
source_lang = en
|
||||
@ -674,48 +602,37 @@ source_lang = en
|
||||
;; Merge locally or make changes on TX side before re-enabling
|
||||
;;trans.ar = installer/resources/eepsite/docroot/help/index_ar.html
|
||||
trans.az = installer/resources/eepsite/docroot/help/index_az.html
|
||||
trans.cs = installer/resources/eepsite/docroot/help/index_cs.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.gan = installer/resources/eepsite/docroot/help/index_gan.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
|
||||
trans.pt = installer/resources/eepsite/docroot/help/index_pt.html
|
||||
trans.pt_BR = installer/resources/eepsite/docroot/help/index_pt_BR.html
|
||||
trans.ro = installer/resources/eepsite/docroot/help/index_ro.html
|
||||
trans.ru_RU = installer/resources/eepsite/docroot/help/index_ru.html
|
||||
trans.sv_SE = installer/resources/eepsite/docroot/help/index_sv.html
|
||||
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
|
||||
trans.zh_TW = installer/resources/eepsite/docroot/help/index_zh_TW.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.gan = apps/routerconsole/resources/docs/readme_gan.html
|
||||
trans.hi = apps/routerconsole/resources/docs/readme_hi.html
|
||||
trans.hu = apps/routerconsole/resources/docs/readme_hu.html
|
||||
;; Java converts id to in
|
||||
trans.id = apps/routerconsole/resources/docs/readme_in.html
|
||||
@ -725,9 +642,10 @@ trans.pl = apps/routerconsole/resources/docs/readme_pl.html
|
||||
trans.pt = apps/routerconsole/resources/docs/readme_pt.html
|
||||
trans.ro = apps/routerconsole/resources/docs/readme_ro.html
|
||||
trans.ru_RU = apps/routerconsole/resources/docs/readme_ru.html
|
||||
trans.sl = apps/routerconsole/resources/docs/readme_sl.html
|
||||
trans.tr_TR = apps/routerconsole/resources/docs/readme_tr.html
|
||||
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
|
||||
|
||||
|
87
Docker.md
87
Docker.md
@ -1,52 +1,13 @@
|
||||
# I2P in Docker
|
||||
|
||||
### Very quick start
|
||||
If you just want to give I2P a quick try or are using it on a home network, follow these steps:
|
||||
|
||||
1. Create two directories `i2pconfig` and `i2ptorrents`
|
||||
2. Create an `.env` file containing the `EXT_PORT` environment variable.
|
||||
3. Copy the following text and save it in a file `docker-compose.yml`
|
||||
```
|
||||
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
|
||||
- "$EXT_PORT":"$EXT_PORT"
|
||||
- "$EXT_PORT":"$EXT_PORT"/udp
|
||||
volumes:
|
||||
- ./i2pconfig:/i2p/.i2p
|
||||
- ./i2ptorrents:/i2psnark
|
||||
```
|
||||
4. Execute `docker-compose up`
|
||||
5. Start a browser and go to `http://127.0.0.1:7657` to complete the setup wizard.
|
||||
|
||||
Note that this quick-start approach is not recommended for production deployments on remote servers. Please read the rest of this document for more information.
|
||||
|
||||
### 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`.
|
||||
|
||||
For advanced configuration only, you can mount the configuration file via `-v ./router.config:/i2p/router.config` to access the settings mentioned in [the i2pd configuration](https://i2pd.readthedocs.io/en/latest/user-guide/configuration/).
|
||||
|
||||
#### 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.
|
||||
|
||||
@ -56,41 +17,33 @@ By the default the image limits the memory available to the Java heap to 512MB.
|
||||
#### Ports
|
||||
There are several ports which are exposed by the image. You can choose which ones to publish depending on your specific needs.
|
||||
|
||||
|Port|Interface|Description|TCP/UDP|
|
||||
|---|---|---|---|
|
||||
|4444|127.0.0.1|HTTP Proxy|TCP|
|
||||
|4445|127.0.0.1|HTTPS Proxy|TCP|
|
||||
|6668|127.0.0.1|IRC Proxy|TCP|
|
||||
|7654|127.0.0.1|I2CP Protocol|TCP|
|
||||
|7656|127.0.0.1|SAM Bridge TCP|TCP|
|
||||
|7657|127.0.0.1|Router console|TCP|
|
||||
|7658|127.0.0.1|I2P Site|TCP|
|
||||
|7659|127.0.0.1|SMTP Proxy|TCP|
|
||||
|7660|127.0.0.1|POP Proxy|TCP|
|
||||
|7652|LAN interface|UPnP|TCP|
|
||||
|7653|LAN interface|UPnP|UDP|
|
||||
|12345|0.0.0.0|I2NP Protocol|TCP and UDP|
|
||||
|Port|Description|TCP/UDP|
|
||||
|---|---|---|
|
||||
|4444|HTTP Proxy|TCP|
|
||||
|4445|HTTPS Proxy|TCP|
|
||||
|6668|IRC Proxy|TCP|
|
||||
|7654|I2CP Protocol|TCP|
|
||||
|7656|SAM Bridge TCP|TCP|
|
||||
|7657|Router console|TCP|
|
||||
|7658|I2P Site|TCP|
|
||||
|7659|SMTP Proxy|TCP|
|
||||
|7660|POP Proxy|TCP|
|
||||
|12345|I2NP Protocol|TCP and UDP|
|
||||
|
||||
You probably want at least the Router Console (7657) and the HTTP Proxy (4444). If you want I2P to be able to receive incoming connections from the internet, and hence not think it's firewalled, publish the I2NP Protocol port (12345) - but make sure you publish to a different random port, otherwise others may be able to guess you're running I2P in a Docker image.
|
||||
|
||||
#### Networking
|
||||
A best-practices guide for cloud deployments is beyond the scope of this document, but in general you should try to minimize the number of published ports, while exposing only the `I2NP` ports to the internet. That means that the services in the list above which are bound to `127.0.0.1` (which include the router console) will need to be accessed via other methods like ssh tunneling or be manually configured to bind to a different interface.
|
||||
|
||||
#### 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 \
|
||||
-e EXT_PORT=54321 \
|
||||
-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 "$EXT_PORT":"$EXT_PORT" \
|
||||
-p "$EXT_PORT":"$EXT_PORT"/udp \
|
||||
geti2p/i2p:latest
|
||||
-p 4444:4444 \
|
||||
-p 6668:6668 \
|
||||
-p 7657:7657 \
|
||||
-p 54321:12345 \
|
||||
-p 54321:12345/udp \ # I2NP port needs TCP and UDP. Change the 54321 to something random, greater than 1024.
|
||||
i2p:latest
|
||||
```
|
||||
|
||||
|
20
Dockerfile
20
Dockerfile
@ -1,27 +1,24 @@
|
||||
FROM alpine:latest as builder
|
||||
FROM jlesage/baseimage:alpine-3.10-glibc as builder
|
||||
|
||||
ENV APP_HOME="/i2p"
|
||||
ARG ANT_VERSION="1.10.15"
|
||||
|
||||
WORKDIR /tmp/build
|
||||
COPY . .
|
||||
|
||||
RUN apk add --no-cache gettext tar bzip2 curl openjdk21 \
|
||||
&& echo "build.built-by=Docker" >> override.properties \
|
||||
&& curl https://dlcdn.apache.org//ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.bz2 | tar -jxf - -C /opt \
|
||||
&& /opt/apache-ant-${ANT_VERSION}/bin/ant preppkg-linux-only \
|
||||
&& rm -rf pkg-temp/osid pkg-temp/lib/wrapper pkg-temp/lib/wrapper.*
|
||||
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.* \
|
||||
&& del-pkg build-base gettext tar bzip2 apache-ant openjdk8
|
||||
|
||||
FROM alpine:latest
|
||||
FROM jlesage/baseimage:alpine-3.10-glibc
|
||||
ENV APP_HOME="/i2p"
|
||||
RUN apk add openjdk21
|
||||
|
||||
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"]
|
||||
|
@ -44,4 +44,6 @@ Supported JVMs:
|
||||
Windows: OpenJDK or Oracle from http://java.com/download
|
||||
Linux: OpenJDK or Oracle from http://java.com/download
|
||||
FreeBSD: OpenJDK or Oracle from http://java.com/download
|
||||
Other operating systems and JVMs: See https://geti2p.net/download
|
||||
Raspberry Pi: Oracle 8 Early Access https://jdk8.java.net/download.html
|
||||
PowerPC: IBM SDK 7 http://www.ibm.com/developerworks/java/jdk/linux/download.html
|
||||
Other operating systems and JVMs: See https://trac.i2p2.de/wiki/java or https://geti2p.net/download
|
||||
|
@ -65,7 +65,7 @@ To uninstall I2P:
|
||||
rm -rf $I2PInstallDir ~/.i2p
|
||||
|
||||
Supported JVMs:
|
||||
All platforms: Java 1.8 or higher required
|
||||
Windows: Latest available from http://java.com/download
|
||||
Linux: Latest available from http://java.com/download
|
||||
Other operating systems and JVMs: See https://geti2p.net/download
|
||||
Windows: Latest available from http://java.com/download (1.7+ supported)
|
||||
Linux: Latest available from http://java.com/download (1.7+ supported)
|
||||
FreeBSD: 1.7-compatible (NIO required)
|
||||
Other operating systems and JVMs: See http://trac.i2p2.de/wiki/java
|
||||
|
39
LICENSE.txt
39
LICENSE.txt
@ -128,9 +128,9 @@ Public domain except as listed below:
|
||||
Copyright (C) 2006 The Android Open Source Project
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
|
||||
ML-KEM:
|
||||
Copyright (c) 2000-2023 The Legion Of The Bouncy Castle Inc. (https://www.bouncycastle.org)
|
||||
See licenses/LICENSE-Bouncycastle.txt
|
||||
SSU HMAC:
|
||||
Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
|
||||
See licenses/LICENSE-SHA256.txt
|
||||
|
||||
|
||||
Installer:
|
||||
@ -186,10 +186,10 @@ Launchers:
|
||||
Copyright (c) 2002-2018 EPFL, Lausanne / Lightbend, Inc. , unless otherwise specified.
|
||||
See licenses/LICENSE-Scala.md
|
||||
|
||||
Java Service Wrapper Community Edition 3.5.60:
|
||||
Java Service Wrapper Community Edition 3.5.44:
|
||||
(Windows: 3.5.25)
|
||||
(not included in most distribution packages)
|
||||
Copyright (C) 1999-2024 Tanuki Software, Ltd. All Rights Reserved.
|
||||
Copyright (C) 1999-2020 Tanuki Software, Ltd. All Rights Reserved.
|
||||
See licenses/LICENSE-Wrapper.txt
|
||||
|
||||
|
||||
@ -212,6 +212,10 @@ Applications:
|
||||
Copyright (c) 2006, Matthew Estes
|
||||
See licenses/LICENSE-BlockFile.txt
|
||||
|
||||
BOB (BOB.jar):
|
||||
Copyright (C) sponge
|
||||
See licenses/COPYING-BOB.txt
|
||||
|
||||
Desktopgui (desktopgui.jar):
|
||||
Copyright (c) Mathias De Maré
|
||||
See licenses/LICENSE-DesktopGUI.txt
|
||||
@ -267,7 +271,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,14 +320,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
|
||||
|
||||
Router Console country coordinates:
|
||||
Adapted from Google Dataset Publishing Language to convert to Mercator
|
||||
CC BY 4.0 https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
SAM (sam.jar):
|
||||
Public domain.
|
||||
|
||||
@ -340,19 +336,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.54 (jasper-runtime.jar):
|
||||
(not included in most distribution packages)
|
||||
Copyright 1999-2024 The Apache Software Foundation
|
||||
Copyright 1999-2021 The Apache Software Foundation
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
See licenses/NOTICE-Tomcat.txt
|
||||
|
||||
@ -366,7 +355,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
|
||||
|
@ -64,9 +64,6 @@ your `~/.gradle/gradle.properties`:
|
||||
systemProp.socksProxyHost=localhost
|
||||
systemProp.socksProxyPort=9150
|
||||
|
||||
### Development builds
|
||||
Automatic CI builds are available at the [continuous integration](https://github.com/i2p/i2p.i2p/actions/workflows/ant.yml) page.
|
||||
|
||||
### Docker
|
||||
For more information how to run I2P in Docker, see [Docker.md](Docker.md)
|
||||
## Contact info
|
||||
|
14
apps/BOB/bob.config
Normal file
14
apps/BOB/bob.config
Normal file
@ -0,0 +1,14 @@
|
||||
#bob.config
|
||||
#Tue Dec 30 00:00:00 UTC 2008
|
||||
# Please leave this file here for testing.
|
||||
# Thank you,
|
||||
# Sponge
|
||||
i2cp.tcp.port=7654
|
||||
BOB.host=localhost
|
||||
inbound.lengthVariance=0
|
||||
i2cp.messageReliability=BestEffort
|
||||
BOB.port=45678
|
||||
outbound.length=1
|
||||
inbound.length=1
|
||||
outbound.lengthVariance=0
|
||||
i2cp.tcp.host=localhost
|
12
apps/BOB/build.gradle
Normal file
12
apps/BOB/build.gradle
Normal file
@ -0,0 +1,12 @@
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile project(':apps:ministreaming')
|
||||
}
|
115
apps/BOB/build.xml
Normal file
115
apps/BOB/build.xml
Normal file
@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="BOB" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project BOB.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar-with-manifest: JAR building (if you are using a manifest)
|
||||
-do-jar-without-manifest: JAR building (if you are not using a manifest)
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="BOB-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
|
||||
<target depends="jar" description="Build BOB into a SINGLE JAR." name="onejar">
|
||||
<!-- Make needed working dirs -->
|
||||
<mkdir dir="${dist.dir}/lib" />
|
||||
<mkdir dir="${dist.dir}/classes" />
|
||||
|
||||
<!-- Copy jars -->
|
||||
<copy todir="${dist.dir}/lib" flatten="true" >
|
||||
<path>
|
||||
<pathelement path="${javac.classpath}" />
|
||||
</path>
|
||||
</copy>
|
||||
<copy todir="${dist.dir}/lib" file="../../build/jbigi.jar" />
|
||||
|
||||
<!-- Extract the classes inside the jar files -->
|
||||
<unjar dest="${dist.dir}/classes" >
|
||||
<fileset dir="${dist.dir}/lib" >
|
||||
<include name="**/*.jar" />
|
||||
</fileset>
|
||||
</unjar>
|
||||
|
||||
<!-- Recombine the classes into a new jar file -->
|
||||
<jar jarfile="${dist.dir}/lib/all-in-one.jar" >
|
||||
<fileset dir="${dist.dir}/classes" />
|
||||
</jar>
|
||||
|
||||
<!-- Clean up work area -->
|
||||
<delete dir="${dist.dir}/classes" followsymlinks="false" includeemptydirs="true"/>
|
||||
|
||||
<!-- Make the single jar file -->
|
||||
<jar jarfile="dist/BOB-one.jar" >
|
||||
<zipfileset src="${dist.jar}" excludes="META-INF/*" />
|
||||
<zipfileset src="${dist.dir}/lib/all-in-one.jar" excludes="**/META-INF/*" />
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="net.i2p.BOB.Main" />
|
||||
</manifest>
|
||||
</jar>
|
||||
|
||||
<!-- Clean up the fake jar file -->
|
||||
<delete file="${dist.dir}/lib/all-in-one.jar" />
|
||||
</target>
|
||||
</project>
|
3
apps/BOB/manifest.mf
Normal file
3
apps/BOB/manifest.mf
Normal file
@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
643
apps/BOB/nbproject/build-impl.xml
Normal file
643
apps/BOB/nbproject/build-impl.xml
Normal file
@ -0,0 +1,643 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
*** GENERATED FROM project.xml - DO NOT EDIT ***
|
||||
*** EDIT ../build.xml INSTEAD ***
|
||||
|
||||
For the purpose of easier reading the script
|
||||
is divided into following sections:
|
||||
|
||||
- initialization
|
||||
- compilation
|
||||
- jar
|
||||
- execution
|
||||
- debugging
|
||||
- javadoc
|
||||
- junit compilation
|
||||
- junit execution
|
||||
- junit debugging
|
||||
- applet
|
||||
- cleanup
|
||||
|
||||
-->
|
||||
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="BOB-impl">
|
||||
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
|
||||
<!--
|
||||
======================
|
||||
INITIALIZATION SECTION
|
||||
======================
|
||||
-->
|
||||
<target name="-pre-init">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="-pre-init" name="-init-private">
|
||||
<property file="nbproject/private/config.properties"/>
|
||||
<property file="nbproject/private/configs/${config}.properties"/>
|
||||
<property file="nbproject/private/private.properties"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private" name="-init-user">
|
||||
<property file="${user.properties.file}"/>
|
||||
<!-- The two properties below are usually overridden -->
|
||||
<!-- by the active platform. Just a fallback. -->
|
||||
<property name="default.javac.source" value="1.8"/>
|
||||
<property name="default.javac.target" value="1.8"/>
|
||||
<property name="javac.release" value="8"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
|
||||
<property file="nbproject/configs/${config}.properties"/>
|
||||
<property file="nbproject/project.properties"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
|
||||
<available file="${manifest.file}" property="manifest.available"/>
|
||||
<condition property="manifest.available+main.class">
|
||||
<and>
|
||||
<isset property="manifest.available"/>
|
||||
<isset property="main.class"/>
|
||||
<not>
|
||||
<equals arg1="${main.class}" arg2="" trim="true"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="manifest.available+main.class+mkdist.available">
|
||||
<and>
|
||||
<istrue value="${manifest.available+main.class}"/>
|
||||
<isset property="libs.CopyLibs.classpath"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="have.tests">
|
||||
<or>
|
||||
<available file="${test.src.dir}"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="have.sources">
|
||||
<or>
|
||||
<available file="${src.dir}"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="netbeans.home+have.tests">
|
||||
<and>
|
||||
<isset property="netbeans.home"/>
|
||||
<isset property="have.tests"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="no.javadoc.preview">
|
||||
<and>
|
||||
<isset property="javadoc.preview"/>
|
||||
<isfalse value="${javadoc.preview}"/>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="run.jvmargs" value=""/>
|
||||
<property name="javac.compilerargs" value=""/>
|
||||
<property name="work.dir" value="${basedir}"/>
|
||||
<condition property="no.deps">
|
||||
<and>
|
||||
<istrue value="${no.dependencies}"/>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="javac.debug" value="true"/>
|
||||
<property name="javadoc.preview" value="true"/>
|
||||
<property name="application.args" value=""/>
|
||||
<property name="source.encoding" value="${file.encoding}"/>
|
||||
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
|
||||
<and>
|
||||
<isset property="javadoc.encoding"/>
|
||||
<not>
|
||||
<equals arg1="${javadoc.encoding}" arg2=""/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
<property name="javadoc.encoding.used" value="${source.encoding}"/>
|
||||
<property name="includes" value="**"/>
|
||||
<property name="excludes" value=""/>
|
||||
<property name="do.depend" value="false"/>
|
||||
<condition property="do.depend.true">
|
||||
<istrue value="${do.depend}"/>
|
||||
</condition>
|
||||
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
|
||||
<and>
|
||||
<isset property="jaxws.endorsed.dir"/>
|
||||
<available file="nbproject/jaxws-build.xml"/>
|
||||
</and>
|
||||
</condition>
|
||||
</target>
|
||||
<target name="-post-init">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
|
||||
<fail unless="src.dir">Must set src.dir</fail>
|
||||
<fail unless="test.src.dir">Must set test.src.dir</fail>
|
||||
<fail unless="build.dir">Must set build.dir</fail>
|
||||
<fail unless="dist.dir">Must set dist.dir</fail>
|
||||
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
|
||||
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
|
||||
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
|
||||
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
|
||||
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
|
||||
<fail unless="dist.jar">Must set dist.jar</fail>
|
||||
</target>
|
||||
<target name="-init-macrodef-property">
|
||||
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute name="name"/>
|
||||
<attribute name="value"/>
|
||||
<sequential>
|
||||
<property name="@{name}" value="${@{value}}"/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-javac">
|
||||
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${src.dir}" name="srcdir"/>
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<attribute default="${javac.classpath}" name="classpath"/>
|
||||
<attribute default="${includes}" name="includes"/>
|
||||
<attribute default="${excludes}" name="excludes"/>
|
||||
<attribute default="${javac.debug}" name="debug"/>
|
||||
<attribute default="/does/not/exist" name="sourcepath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" release="${javac.release}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
|
||||
<customize/>
|
||||
</javac>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${src.dir}" name="srcdir"/>
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<attribute default="${javac.classpath}" name="classpath"/>
|
||||
<sequential>
|
||||
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
</depend>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${build.classes.dir}" name="destdir"/>
|
||||
<sequential>
|
||||
<fail unless="javac.includes">Must set javac.includes</fail>
|
||||
<pathconvert pathsep="," property="javac.includes.binary">
|
||||
<path>
|
||||
<filelist dir="@{destdir}" files="${javac.includes}"/>
|
||||
</path>
|
||||
<globmapper from="*.java" to="*.class"/>
|
||||
</pathconvert>
|
||||
<delete>
|
||||
<files includes="${javac.includes.binary}"/>
|
||||
</delete>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-junit">
|
||||
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${includes}" name="includes"/>
|
||||
<attribute default="${excludes}" name="excludes"/>
|
||||
<attribute default="**" name="testincludes"/>
|
||||
<sequential>
|
||||
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
|
||||
<batchtest todir="${build.test.results.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
|
||||
<filename name="@{testincludes}"/>
|
||||
</fileset>
|
||||
</batchtest>
|
||||
<classpath>
|
||||
<path path="${run.test.classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="test-sys-prop."/>
|
||||
<mapper from="test-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<formatter type="brief" usefile="false"/>
|
||||
<formatter type="xml"/>
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
</junit>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target depends="-init-debug-args" name="-init-macrodef-nbjpda">
|
||||
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${main.class}" name="name"/>
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<attribute default="" name="stopclassname"/>
|
||||
<sequential>
|
||||
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
</nbjpdastart>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${build.classes.dir}" name="dir"/>
|
||||
<sequential>
|
||||
<nbjpdareload>
|
||||
<fileset dir="@{dir}" includes="${fix.classes}">
|
||||
<include name="${fix.includes}*.class"/>
|
||||
</fileset>
|
||||
</nbjpdareload>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-debug-args">
|
||||
<property name="version-output" value="java version "${ant.java.version}"/>
|
||||
<condition property="have-jdk-older-than-1.4">
|
||||
<or>
|
||||
<contains string="${version-output}" substring="java version "1.0"/>
|
||||
<contains string="${version-output}" substring="java version "1.1"/>
|
||||
<contains string="${version-output}" substring="java version "1.2"/>
|
||||
<contains string="${version-output}" substring="java version "1.3"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
|
||||
<istrue value="${have-jdk-older-than-1.4}"/>
|
||||
</condition>
|
||||
<condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
|
||||
<os family="windows"/>
|
||||
</condition>
|
||||
<condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
|
||||
<isset property="debug.transport"/>
|
||||
</condition>
|
||||
</target>
|
||||
<target depends="-init-debug-args" name="-init-macrodef-debug">
|
||||
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<attribute default="${main.class}" name="classname"/>
|
||||
<attribute default="${debug.classpath}" name="classpath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<java classname="@{classname}" dir="${work.dir}" fork="true">
|
||||
<jvmarg line="${debug-args-line}"/>
|
||||
<jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="run-sys-prop."/>
|
||||
<mapper from="run-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<customize/>
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-macrodef-java">
|
||||
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<attribute default="${main.class}" name="classname"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<java classname="@{classname}" dir="${work.dir}" fork="true">
|
||||
<jvmarg line="${run.jvmargs}"/>
|
||||
<classpath>
|
||||
<path path="${run.classpath}"/>
|
||||
</classpath>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="run-sys-prop."/>
|
||||
<mapper from="run-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<customize/>
|
||||
</java>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</target>
|
||||
<target name="-init-presetdef-jar">
|
||||
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
|
||||
<jar compress="${jar.compress}" jarfile="${dist.jar}">
|
||||
<j2seproject1:fileset dir="${build.classes.dir}"/>
|
||||
</jar>
|
||||
</presetdef>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
|
||||
<!--
|
||||
===================
|
||||
COMPILATION SECTION
|
||||
===================
|
||||
-->
|
||||
<target depends="init" name="deps-jar" unless="no.deps"/>
|
||||
<target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
|
||||
<target depends="init" name="-check-automatic-build">
|
||||
<available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
|
||||
</target>
|
||||
<target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
|
||||
<antcall target="clean"/>
|
||||
</target>
|
||||
<target depends="init,deps-jar" name="-pre-pre-compile">
|
||||
<mkdir dir="${build.classes.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target if="do.depend.true" name="-compile-depend">
|
||||
<j2seproject3:depend/>
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
|
||||
<j2seproject3:javac/>
|
||||
<copy todir="${build.classes.dir}">
|
||||
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
|
||||
<target name="-pre-compile-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
|
||||
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
|
||||
<j2seproject3:force-recompile/>
|
||||
<j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
|
||||
</target>
|
||||
<target name="-post-compile-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
|
||||
<!--
|
||||
====================
|
||||
JAR BUILDING SECTION
|
||||
====================
|
||||
-->
|
||||
<target depends="init" name="-pre-pre-jar">
|
||||
<dirname file="${dist.jar}" property="dist.jar.dir"/>
|
||||
<mkdir dir="${dist.jar.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-jar">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
|
||||
<j2seproject1:jar/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
|
||||
<j2seproject1:jar manifest="${manifest.file}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
|
||||
<j2seproject1:jar manifest="${manifest.file}">
|
||||
<j2seproject1:manifest>
|
||||
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
|
||||
</j2seproject1:manifest>
|
||||
</j2seproject1:jar>
|
||||
<echo>To run this application from the command line without Ant, try:</echo>
|
||||
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
|
||||
<property location="${dist.jar}" name="dist.jar.resolved"/>
|
||||
<pathconvert property="run.classpath.with.dist.jar">
|
||||
<path path="${run.classpath}"/>
|
||||
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
|
||||
</pathconvert>
|
||||
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
|
||||
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
|
||||
<pathconvert property="run.classpath.without.build.classes.dir">
|
||||
<path path="${run.classpath}"/>
|
||||
<map from="${build.classes.dir.resolved}" to=""/>
|
||||
</pathconvert>
|
||||
<pathconvert pathsep=" " property="jar.classpath">
|
||||
<path path="${run.classpath.without.build.classes.dir}"/>
|
||||
<chainedmapper>
|
||||
<flattenmapper/>
|
||||
<globmapper from="*" to="lib/*"/>
|
||||
</chainedmapper>
|
||||
</pathconvert>
|
||||
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
|
||||
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main.class}"/>
|
||||
<attribute name="Class-Path" value="${jar.classpath}"/>
|
||||
</manifest>
|
||||
</copylibs>
|
||||
<echo>To run this application from the command line without Ant, try:</echo>
|
||||
<property location="${dist.jar}" name="dist.jar.resolved"/>
|
||||
<echo>java -jar "${dist.jar.resolved}"</echo>
|
||||
</target>
|
||||
<target name="-post-jar">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
|
||||
<!--
|
||||
=================
|
||||
EXECUTION SECTION
|
||||
=================
|
||||
-->
|
||||
<target depends="init,compile" description="Run a main class." name="run">
|
||||
<j2seproject1:java>
|
||||
<customize>
|
||||
<arg line="${application.args}"/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
</target>
|
||||
<target name="-do-not-recompile">
|
||||
<property name="javac.includes.binary" value=""/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-single" name="run-single">
|
||||
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
|
||||
<j2seproject1:java classname="${run.class}"/>
|
||||
</target>
|
||||
<!--
|
||||
=================
|
||||
DEBUGGING SECTION
|
||||
=================
|
||||
-->
|
||||
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
|
||||
<j2seproject1:nbjpdastart name="${debug.class}"/>
|
||||
</target>
|
||||
<target depends="init,compile" name="-debug-start-debuggee">
|
||||
<j2seproject3:debug>
|
||||
<customize>
|
||||
<arg line="${application.args}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
|
||||
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
|
||||
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
|
||||
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
|
||||
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
|
||||
<j2seproject3:debug classname="${debug.class}"/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
|
||||
<target depends="init" name="-pre-debug-fix">
|
||||
<fail unless="fix.includes">Must set fix.includes</fail>
|
||||
<property name="javac.includes" value="${fix.includes}.java"/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
|
||||
<j2seproject1:nbjpdareload/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
|
||||
<!--
|
||||
===============
|
||||
JAVADOC SECTION
|
||||
===============
|
||||
-->
|
||||
<target depends="init" name="-javadoc-build">
|
||||
<mkdir dir="${dist.javadoc.dir}"/>
|
||||
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
|
||||
<classpath>
|
||||
<path path="${javac.classpath}"/>
|
||||
</classpath>
|
||||
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
|
||||
<filename name="**/*.java"/>
|
||||
</fileset>
|
||||
</javadoc>
|
||||
</target>
|
||||
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
|
||||
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
|
||||
</target>
|
||||
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
|
||||
<!--
|
||||
=========================
|
||||
JUNIT COMPILATION SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
|
||||
<mkdir dir="${build.test.classes.dir}"/>
|
||||
</target>
|
||||
<target name="-pre-compile-test">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target if="do.depend.true" name="-compile-test-depend">
|
||||
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
|
||||
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
|
||||
<copy todir="${build.test.classes.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile-test">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
|
||||
<target name="-pre-compile-test-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
|
||||
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
|
||||
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
|
||||
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
|
||||
<copy todir="${build.test.classes.dir}">
|
||||
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="-post-compile-test-single">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
|
||||
<!--
|
||||
=======================
|
||||
JUNIT EXECUTION SECTION
|
||||
=======================
|
||||
-->
|
||||
<target depends="init" if="have.tests" name="-pre-test-run">
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
|
||||
<j2seproject3:junit testincludes="**/*Test.java"/>
|
||||
</target>
|
||||
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
|
||||
<fail if="tests.failed">Some tests failed; see details above.</fail>
|
||||
</target>
|
||||
<target depends="init" if="have.tests" name="test-report"/>
|
||||
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
|
||||
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
|
||||
<target depends="init" if="have.tests" name="-pre-test-run-single">
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
|
||||
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
|
||||
<j2seproject3:junit excludes="" includes="${test.includes}"/>
|
||||
</target>
|
||||
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
|
||||
<fail if="tests.failed">Some tests failed; see details above.</fail>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
|
||||
<!--
|
||||
=======================
|
||||
JUNIT DEBUGGING SECTION
|
||||
=======================
|
||||
-->
|
||||
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
|
||||
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
|
||||
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
|
||||
<delete file="${test.report.file}"/>
|
||||
<mkdir dir="${build.test.results.dir}"/>
|
||||
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
|
||||
<customize>
|
||||
<syspropertyset>
|
||||
<propertyref prefix="test-sys-prop."/>
|
||||
<mapper from="test-sys-prop.*" to="*" type="glob"/>
|
||||
</syspropertyset>
|
||||
<arg value="${test.class}"/>
|
||||
<arg value="showoutput=true"/>
|
||||
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
|
||||
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
|
||||
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
|
||||
</target>
|
||||
<target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
|
||||
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
|
||||
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
|
||||
</target>
|
||||
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
|
||||
<!--
|
||||
=========================
|
||||
APPLET EXECUTION SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile-single" name="run-applet">
|
||||
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
|
||||
<j2seproject1:java classname="sun.applet.AppletViewer">
|
||||
<customize>
|
||||
<arg value="${applet.url}"/>
|
||||
</customize>
|
||||
</j2seproject1:java>
|
||||
</target>
|
||||
<!--
|
||||
=========================
|
||||
APPLET DEBUGGING SECTION
|
||||
=========================
|
||||
-->
|
||||
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
|
||||
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
|
||||
<j2seproject3:debug classname="sun.applet.AppletViewer">
|
||||
<customize>
|
||||
<arg value="${applet.url}"/>
|
||||
</customize>
|
||||
</j2seproject3:debug>
|
||||
</target>
|
||||
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
|
||||
<!--
|
||||
===============
|
||||
CLEANUP SECTION
|
||||
===============
|
||||
-->
|
||||
<target depends="init" name="deps-clean" unless="no.deps"/>
|
||||
<target depends="init" name="-do-clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${dist.dir}"/>
|
||||
</target>
|
||||
<target name="-post-clean">
|
||||
<!-- Empty placeholder for easier customization. -->
|
||||
<!-- You can override this target in the ../build.xml file. -->
|
||||
</target>
|
||||
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
|
||||
</project>
|
8
apps/BOB/nbproject/genfiles.properties
Normal file
8
apps/BOB/nbproject/genfiles.properties
Normal file
@ -0,0 +1,8 @@
|
||||
build.xml.data.CRC32=209349b6
|
||||
build.xml.script.CRC32=403e69e6
|
||||
build.xml.stylesheet.CRC32=958a1d3e
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=209349b6
|
||||
nbproject/build-impl.xml.script.CRC32=c51e188e
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=65b8de21
|
84
apps/BOB/nbproject/project.properties
Normal file
84
apps/BOB/nbproject/project.properties
Normal file
@ -0,0 +1,84 @@
|
||||
application.homepage=http://bob.i2p/
|
||||
application.title=BOB
|
||||
application.vendor=Sponge
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=8
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=8
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
build.generated.sources.dir=${build.dir}/generated-sources
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/BOB.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=**/*.html,**/*.txt
|
||||
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
|
||||
file.reference.i2p.jar=../../core/java/build/i2p.jar
|
||||
file.reference.mstreaming.jar=../ministreaming/java/build/mstreaming.jar
|
||||
includes=**
|
||||
jar.compress=true
|
||||
javac.classpath=\
|
||||
${file.reference.mstreaming.jar}:\
|
||||
${file.reference.i2p.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.version=1.8
|
||||
javac.source=${javac.version}
|
||||
javac.target=${javac.version}
|
||||
javac.release=8
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit.classpath}:\
|
||||
${libs.junit_4.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
|
||||
jnlp.codebase.type=local
|
||||
jnlp.codebase.url=file:/usblv/NetBeansProjects/i2p.i2p/apps/BOB/dist
|
||||
jnlp.descriptor=application
|
||||
jnlp.enabled=false
|
||||
jnlp.offline-allowed=false
|
||||
jnlp.signed=false
|
||||
main.class=net.i2p.BOB.Main
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
platform.active=default_platform
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project
|
||||
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
|
||||
# or test-sys-prop.name=value to set system properties for unit tests):
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
16
apps/BOB/nbproject/project.xml
Normal file
16
apps/BOB/nbproject/project.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>BOB</name>
|
||||
<minimum-ant-version>1.9.8</minimum-ant-version>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
542
apps/BOB/src/net/i2p/BOB/BOB.java
Normal file
542
apps/BOB/src/net/i2p/BOB/BOB.java
Normal file
@ -0,0 +1,542 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import static net.i2p.app.ClientAppState.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.app.*;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.PortMapper;
|
||||
import net.i2p.util.SimpleTimer2;
|
||||
|
||||
/**
|
||||
* <span style="font-size:8px;font-family:courier;color:#EEEEEE;background-color:#000000">
|
||||
* ################################################################################<br>
|
||||
* ############################.#..........#..#..........##########################<br>
|
||||
* #######################......................................###################<br>
|
||||
* ####################...........................#.......#........################<br>
|
||||
* #################..................##...................#.........##############<br>
|
||||
* ###############................###...####.....#..###.....#.........#############<br>
|
||||
* #############...........###..#..###...#####...###.##........#.......############<br>
|
||||
* ###########................#......##...#####...##..##.......#..#........########<br>
|
||||
* ##########.........................#....##.##..#...##.....................######<br>
|
||||
* #########...................................#....#.........................#####<br>
|
||||
* ########.........................................#...............#..........####<br>
|
||||
* ########.........................................#..........#######..........###<br>
|
||||
* #######.................................................############..........##<br>
|
||||
* #######..........................................####################.........##<br>
|
||||
* #######............####################......########################.........##<br>
|
||||
* ######.............###############################################.##.........##<br>
|
||||
* ######............################################################..##........##<br>
|
||||
* ######............################################################..##........##<br>
|
||||
* ######.............##############################################..##.........##<br>
|
||||
* ######............##############################################...##..........#<br>
|
||||
* ######............#..###########################################...##..........#<br>
|
||||
* ######.............#############################################....#..........#<br>
|
||||
* #######...........###############################################..##.........##<br>
|
||||
* #######...........#####.#.#.#.########################.....#.####...##........##<br>
|
||||
* ######............#..............##################.................##.........#<br>
|
||||
* ######................####.........###############........#####......##........#<br>
|
||||
* ######..............####..#.........############.......##.#.######...##.......##<br>
|
||||
* ######.................#.####.........########...........##....###...##.......##<br>
|
||||
* #######....#....###...................#######...............#...###..##.......##<br>
|
||||
* #######.........###..###.....###.......######.##.#####.........####..##.......##<br>
|
||||
* #######.....#...##############.........############......###########.###......##<br>
|
||||
* #######....##...##########.......##...##############......#.############.....###<br>
|
||||
* ########....#..########......######...##################################....####<br>
|
||||
* ########....##.####################...##################################....####<br>
|
||||
* ########..#.##..###################..##################################..#..####<br>
|
||||
* ##########..###..#################...##################################...#.####<br>
|
||||
* #########....##...##############....########..#####.################.##..#.#####<br>
|
||||
* ############.##....##########.......#########.###.......###########..#.#########<br>
|
||||
* ###############.....#######...#.......########.....##.....######.....###########<br>
|
||||
* ###############......###....##..........##.......######....#.........#.#########<br>
|
||||
* ##############............##..................##########..............##########<br>
|
||||
* ##############..............................##########..#.............##########<br>
|
||||
* ###############.......##..................#####..............####....###########<br>
|
||||
* ###############.......#####.......#.............####.....#######.....###########<br>
|
||||
* ################...#...####......##################.....########....############<br>
|
||||
* ################...##..#####.........####.##.....#....##########....############<br>
|
||||
* ##################..##..####...........#####.#....############.....#############<br>
|
||||
* ##################......#####.................################....##############<br>
|
||||
* ###################.....####..........##########..###########....###############<br>
|
||||
* ####################..#..#..........................########.....###############<br>
|
||||
* #####################.##.......###.................########....#################<br>
|
||||
* ######################.........#.......#.##.###############....#################<br>
|
||||
* #############.#######...............#####################....###################<br>
|
||||
* ###..#.....##...####..........#.....####################....####################<br>
|
||||
* ####......##........................##################....######################<br>
|
||||
* #.##...###..............###.........###############......#######################<br>
|
||||
* #...###..##............######...........................########################<br>
|
||||
* ##.......###..........##########....#...#...........############################<br>
|
||||
* ##.........##.......############################################################<br>
|
||||
* ###........##.....##############################################################<br>
|
||||
* ####.............###############################################################<br>
|
||||
* ######.........#################################################################<br>
|
||||
* #########....###################################################################<br>
|
||||
* ################################################################################<br>
|
||||
* </span>
|
||||
* BOB, main command socket listener, launches the command parser engine.
|
||||
*
|
||||
* @author sponge
|
||||
* @deprecated Please port applications to SAMv3
|
||||
*/
|
||||
@Deprecated
|
||||
public class BOB implements Runnable, ClientApp {
|
||||
|
||||
public final static String PROP_CONFIG_LOCATION = "BOB.config";
|
||||
public final static String PROP_BOB_PORT = "BOB.port";
|
||||
public final static String PROP_BOB_HOST = "BOB.host";
|
||||
public final static String PROP_CFG_VER = "BOB.CFG.VER";
|
||||
|
||||
/** unused when started via the ClientApp interface */
|
||||
private static BOB _bob;
|
||||
|
||||
private final NamedDB database;
|
||||
private final Properties props = new Properties();
|
||||
private final AtomicBoolean spin = new AtomicBoolean(true);
|
||||
private static final String P_RUNNING = "RUNNING";
|
||||
private static final String P_STARTING = "STARTING";
|
||||
private static final String P_STOPPING = "STOPPING";
|
||||
private final AtomicBoolean lock = new AtomicBoolean(false);
|
||||
// no longer used.
|
||||
// private static int maxConnections = 0;
|
||||
|
||||
private final I2PAppContext _context;
|
||||
private final Logger _log;
|
||||
private final ClientAppManager _mgr;
|
||||
private final String[] _args;
|
||||
private volatile ClientAppState _state = UNINITIALIZED;
|
||||
|
||||
private volatile ServerSocket listener;
|
||||
private volatile Thread _runner;
|
||||
private volatile boolean _warned;
|
||||
|
||||
/**
|
||||
* Stop BOB gracefully
|
||||
* @deprecated unused
|
||||
*/
|
||||
@Deprecated
|
||||
public synchronized static void stop() {
|
||||
if (_bob != null)
|
||||
_bob.shutdown(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* For ClientApp interface.
|
||||
* Does NOT open the listener socket or start threads; caller must call startup()
|
||||
*
|
||||
* @param mgr may be null
|
||||
* @param args non-null
|
||||
* @since 0.9.10
|
||||
*/
|
||||
public BOB(I2PAppContext context, ClientAppManager mgr, String[] args) {
|
||||
_context = context;
|
||||
// If we were run from command line, log to stdout
|
||||
boolean logToStdout = false;
|
||||
URL classResource = BOB.class.getResource("BOB.class");
|
||||
if (classResource != null) {
|
||||
String classPath = classResource.toString();
|
||||
if (classPath.startsWith("jar")) {
|
||||
String manifestPath = classPath.substring(0, classPath.lastIndexOf('!') + 1) +
|
||||
"/META-INF/MANIFEST.MF";
|
||||
try {
|
||||
Manifest manifest = new Manifest(new URL(manifestPath).openStream());
|
||||
Attributes attrs = manifest.getMainAttributes();
|
||||
String mainClass = attrs.getValue("Main-Class");
|
||||
if ("net.i2p.BOB.Main".equals(mainClass))
|
||||
logToStdout = true;
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
_log = new Logger(context.logManager().getLog(BOB.class), logToStdout);
|
||||
|
||||
_mgr = mgr;
|
||||
_args = args;
|
||||
_state = INITIALIZED;
|
||||
database = new NamedDB();
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for incoming connections and handle them
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public synchronized static void main(String[] args) {
|
||||
try {
|
||||
_bob = new BOB(I2PAppContext.getGlobalContext(), null, args);
|
||||
_bob.startup();
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
private void loadConfig() {
|
||||
int i = 0;
|
||||
boolean save = false;
|
||||
// Set up all defaults to be passed forward to other threads.
|
||||
// Re-reading the config file in each thread is pretty damn stupid.
|
||||
String configLocation = System.getProperty(PROP_CONFIG_LOCATION, "bob.config");
|
||||
// This is here just to ensure there is no interference with our threadgroups.
|
||||
SimpleTimer2 Y2 = SimpleTimer2.getInstance();
|
||||
i = Y2.hashCode();
|
||||
{
|
||||
File cfg = new File(configLocation);
|
||||
if (!cfg.isAbsolute()) {
|
||||
cfg = new File(_context.getConfigDir(), configLocation);
|
||||
}
|
||||
FileInputStream fi = null;
|
||||
try {
|
||||
fi = new FileInputStream(cfg);
|
||||
props.load(fi);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
_log.warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.", fnfe);
|
||||
save = true;
|
||||
} catch (IOException ioe) {
|
||||
_log.warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.", ioe);
|
||||
} finally {
|
||||
if (fi != null) try { fi.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
// Global router and client API configurations that are missing are set to defaults here.
|
||||
if (!props.containsKey(I2PClient.PROP_TCP_HOST)) {
|
||||
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
|
||||
save = true;
|
||||
}
|
||||
if (!props.containsKey(I2PClient.PROP_TCP_PORT)) {
|
||||
props.setProperty(I2PClient.PROP_TCP_PORT, Integer.toString(I2PClient.DEFAULT_LISTEN_PORT));
|
||||
save = true;
|
||||
}
|
||||
if (!props.containsKey(PROP_BOB_PORT)) {
|
||||
props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
|
||||
save = true;
|
||||
}
|
||||
if (!props.containsKey("inbound.length")) {
|
||||
props.setProperty("inbound.length", "3");
|
||||
save = true;
|
||||
}
|
||||
if (!props.containsKey("outbound.length")) {
|
||||
props.setProperty("outbound.length", "3");
|
||||
save = true;
|
||||
}
|
||||
if (!props.containsKey("inbound.lengthVariance")) {
|
||||
props.setProperty("inbound.lengthVariance", "0");
|
||||
save = true;
|
||||
}
|
||||
if (!props.containsKey("outbound.lengthVariance")) {
|
||||
props.setProperty("outbound.lengthVariance", "0");
|
||||
save = true;
|
||||
}
|
||||
if (!props.containsKey(PROP_BOB_HOST)) {
|
||||
props.setProperty(PROP_BOB_HOST, "localhost");
|
||||
save = true;
|
||||
}
|
||||
// PROP_RELIABILITY_NONE, PROP_RELIABILITY_BEST_EFFORT, PROP_RELIABILITY_GUARANTEED
|
||||
if (!props.containsKey(PROP_CFG_VER)) {
|
||||
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
|
||||
props.setProperty(PROP_CFG_VER,"1");
|
||||
save = true;
|
||||
}
|
||||
if (save) {
|
||||
File cfg = new File(configLocation);
|
||||
if (!cfg.isAbsolute()) {
|
||||
cfg = new File(_context.getConfigDir(), configLocation);
|
||||
}
|
||||
FileOutputStream fo = null;
|
||||
try {
|
||||
_log.warn("Writing new defaults file " + cfg.getAbsolutePath());
|
||||
fo = new FileOutputStream(cfg);
|
||||
props.store(fo, cfg.getAbsolutePath());
|
||||
} catch (IOException ioe) {
|
||||
_log.error("IOException on BOB config file " + cfg.getAbsolutePath(), ioe);
|
||||
} finally {
|
||||
if (fo != null) try { fo.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
private void startListener() throws IOException {
|
||||
listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
|
||||
listener.setSoTimeout(500); // .5 sec
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
private void startThread() {
|
||||
I2PAppThread t = new I2PAppThread(this, "BOBListener");
|
||||
t.start();
|
||||
_runner = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
public void run() {
|
||||
if (listener == null) return;
|
||||
changeState(RUNNING);
|
||||
_log.info("BOB is now running.");
|
||||
if (_mgr != null)
|
||||
_mgr.register(this);
|
||||
_context.portMapper().register(PortMapper.SVC_BOB, props.getProperty(PROP_BOB_HOST),
|
||||
Integer.parseInt(props.getProperty(PROP_BOB_PORT)));
|
||||
|
||||
int i = 0;
|
||||
boolean g = false;
|
||||
spin.set(true);
|
||||
try {
|
||||
Socket server = null;
|
||||
|
||||
while (spin.get()) {
|
||||
//DoCMDS connection;
|
||||
|
||||
try {
|
||||
server = listener.accept();
|
||||
server.setKeepAlive(true);
|
||||
g = true;
|
||||
} catch (ConnectException ce) {
|
||||
g = false;
|
||||
} catch (SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
|
||||
if (g) {
|
||||
if (!_warned) {
|
||||
_warned = true;
|
||||
String s = "BOB is deprecated. Please port applications to SAMv3.";
|
||||
_context.logManager().getLog(BOB.class).logAlways(Log.WARN, s);
|
||||
_log.warn(s);
|
||||
}
|
||||
DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log);
|
||||
Thread t = new I2PAppThread(conn_c);
|
||||
t.setName("BOB.DoCMDS " + i);
|
||||
t.start();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
changeState(STOPPING);
|
||||
} catch (Exception e) {
|
||||
if (spin.get())
|
||||
_log.error("Unexpected error while listening for connections", e);
|
||||
else
|
||||
e = null;
|
||||
changeState(STOPPING, e);
|
||||
} finally {
|
||||
_log.info("BOB is now shutting down...");
|
||||
_context.portMapper().unregister(PortMapper.SVC_BOB);
|
||||
// Clean up everything.
|
||||
try {
|
||||
listener.close();
|
||||
} catch (Exception ex) {
|
||||
// nop
|
||||
}
|
||||
// Find all our "BOB.DoCMDS" threads, wait for them to be finished.
|
||||
// We could order them to stop, but that could cause nasty issues in the locks.
|
||||
visitAllThreads();
|
||||
database.getReadLock();
|
||||
NamedDB nickinfo;
|
||||
try {
|
||||
for (Object ndb : database.values()) {
|
||||
nickinfo = (NamedDB) ndb;
|
||||
nickinfo.getReadLock();
|
||||
boolean released = false;
|
||||
try {
|
||||
if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
|
||||
nickinfo.releaseReadLock();
|
||||
released = true;
|
||||
nickinfo.getWriteLock();
|
||||
try {
|
||||
nickinfo.add(P_STOPPING, Boolean.TRUE);
|
||||
} finally {
|
||||
nickinfo.releaseWriteLock();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (!released)
|
||||
nickinfo.releaseReadLock();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
database.releaseReadLock();
|
||||
}
|
||||
changeState(STOPPED);
|
||||
_log.info("BOB is now stopped.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the root thread group,
|
||||
* then find all theads with certain names and wait for them all to be dead.
|
||||
*
|
||||
*/
|
||||
private static void visitAllThreads() {
|
||||
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
|
||||
while (root.getParent() != null) {
|
||||
root = root.getParent();
|
||||
}
|
||||
|
||||
// Visit each thread group
|
||||
waitjoin(root, 0, root.getName());
|
||||
}
|
||||
|
||||
private static void waitjoin(ThreadGroup group, int level, String tn) {
|
||||
// Get threads in `group'
|
||||
int numThreads = group.activeCount();
|
||||
Thread[] threads = new Thread[numThreads * 2];
|
||||
numThreads = group.enumerate(threads, false);
|
||||
// Enumerate each thread in `group' and wait for it to stop if it is one of ours.
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
// Get thread
|
||||
Thread thread = threads[i];
|
||||
if (thread.getName().startsWith("BOB.DoCMDS ")) {
|
||||
try {
|
||||
if (thread.isAlive()) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
//nop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get thread subgroups of `group'
|
||||
int numGroups = group.activeGroupCount();
|
||||
ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
|
||||
numGroups = group.enumerate(groups, false);
|
||||
|
||||
// Recursively visit each subgroup
|
||||
for (int i = 0; i < numGroups; i++) {
|
||||
waitjoin(groups[i], level + 1, groups[i].getName());
|
||||
}
|
||||
}
|
||||
|
||||
////// begin ClientApp interface
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
@Override
|
||||
public void startup() throws IOException {
|
||||
if (_state != INITIALIZED)
|
||||
return;
|
||||
changeState(STARTING);
|
||||
try {
|
||||
startListener();
|
||||
} catch (IOException e) {
|
||||
_log.error("Error starting BOB on"
|
||||
+ props.getProperty(PROP_BOB_HOST)
|
||||
+ ":" + props.getProperty(PROP_BOB_PORT), e);
|
||||
changeState(START_FAILED, e);
|
||||
throw e;
|
||||
}
|
||||
startThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
@Override
|
||||
public void shutdown(String[] args) {
|
||||
if (_state != RUNNING)
|
||||
return;
|
||||
changeState(STOPPING);
|
||||
spin.set(false);
|
||||
if (_runner != null)
|
||||
_runner.interrupt();
|
||||
else
|
||||
changeState(STOPPED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
@Override
|
||||
public ClientAppState getState() {
|
||||
return _state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "BOB";
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "BOB " + Arrays.toString(_args);
|
||||
}
|
||||
|
||||
////// end ClientApp interface
|
||||
////// begin ClientApp helpers
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
private void changeState(ClientAppState state) {
|
||||
changeState(state, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.10
|
||||
*/
|
||||
private synchronized void changeState(ClientAppState state, Exception e) {
|
||||
_state = state;
|
||||
if (_mgr != null)
|
||||
_mgr.notify(this, state, null, e);
|
||||
}
|
||||
|
||||
////// end ClientApp helpers
|
||||
}
|
996
apps/BOB/src/net/i2p/BOB/DoCMDS.java
Normal file
996
apps/BOB/src/net/i2p/BOB/DoCMDS.java
Normal file
@ -0,0 +1,996 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.net.Socket;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PClientFactory;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
// needed only for debugging.
|
||||
// import java.util.logging.Level;
|
||||
// import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Simplistic command parser for BOB
|
||||
*
|
||||
* @author sponge
|
||||
*
|
||||
*/
|
||||
public class DoCMDS implements Runnable {
|
||||
|
||||
// FIX ME
|
||||
// I need a better way to do versioning, but this will do for now.
|
||||
public static final String BMAJ = "00", BMIN = "00", BREV = "10", BEXT = "";
|
||||
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
|
||||
private final Socket server;
|
||||
private final Properties props;
|
||||
private final NamedDB database;
|
||||
private String line;
|
||||
private Destination d;
|
||||
private ByteArrayOutputStream prikey;
|
||||
private boolean dk, ns, ip, op;
|
||||
private NamedDB nickinfo;
|
||||
private final Logger _log;
|
||||
private final AtomicBoolean LIVE;
|
||||
private final AtomicBoolean lock;
|
||||
/* database strings */
|
||||
private static final String P_DEST = "DESTINATION";
|
||||
private static final String P_INHOST = "INHOST";
|
||||
private static final String P_INPORT = "INPORT";
|
||||
private static final String P_KEYS = "KEYS";
|
||||
private static final String P_NICKNAME = "NICKNAME";
|
||||
private static final String P_OUTHOST = "OUTHOST";
|
||||
private static final String P_OUTPORT = "OUTPORT";
|
||||
private static final String P_PROPERTIES = "PROPERTIES";
|
||||
private static final String P_QUIET = "QUIET";
|
||||
private static final String P_RUNNING = "RUNNING";
|
||||
private static final String P_STARTING = "STARTING";
|
||||
private static final String P_STOPPING = "STOPPING";
|
||||
|
||||
/* command strings */
|
||||
private static final String C_help = "help";
|
||||
private static final String C_clear = "clear";
|
||||
private static final String C_getdest = "getdest";
|
||||
private static final String C_getkeys = "getkeys";
|
||||
private static final String C_getnick = "getnick";
|
||||
private static final String C_inhost = "inhost";
|
||||
private static final String C_inport = "inport";
|
||||
private static final String C_list = "list";
|
||||
private static final String C_lookup = "lookup";
|
||||
private static final String C_newkeys = "newkeys";
|
||||
private static final String C_option = "option";
|
||||
private static final String C_outhost = "outhost";
|
||||
private static final String C_outport = "outport";
|
||||
private static final String C_quiet = "quiet";
|
||||
private static final String C_quit = "quit";
|
||||
private static final String C_setkeys = "setkeys";
|
||||
private static final String C_setnick = "setnick";
|
||||
private static final String C_show = "show";
|
||||
private static final String C_show_props = "showprops";
|
||||
private static final String C_start = "start";
|
||||
private static final String C_status = "status";
|
||||
private static final String C_stop = "stop";
|
||||
private static final String C_verify = "verify";
|
||||
private static final String C_visit = "visit";
|
||||
private static final String C_zap = "zap";
|
||||
|
||||
/* all the commands available, plus description */
|
||||
private static final String C_ALL[][] = {
|
||||
{C_help, C_help + " <command> * Get help on a command."},
|
||||
{C_clear, C_clear + " * Clear the current nickname out of the list."},
|
||||
{C_getdest, C_getdest + " * Return the destination for the current nickname."},
|
||||
{C_getkeys, C_getkeys + " * Return the keypair for the current nickname."},
|
||||
{C_getnick, C_getnick + " tunnelname * Set the nickname from the database."},
|
||||
{C_inhost, C_inhost + " hostname | IP * Set the inbound hostname or IP."},
|
||||
{C_inport, C_inport + " port_number * Set the inbound port number nickname listens on."},
|
||||
{C_list, C_list + " * List all tunnels."},
|
||||
{C_lookup, C_lookup + " * Lookup an i2p address."},
|
||||
{C_newkeys, C_newkeys + " * Generate a new keypair for the current nickname."},
|
||||
{C_option, C_option + " I2CPoption=something * Set an I2CP option. NOTE: Don't use any spaces."},
|
||||
{C_outhost, C_outhost + " hostname | IP * Set the outbound hostname or IP."},
|
||||
{C_outport, C_outport + " port_number * Set the outbound port that nickname contacts."},
|
||||
{C_quiet, C_quiet + " True | False * Don't send to the application the incoming destination."},
|
||||
{C_quit, C_quit + " * Quits this session with BOB."},
|
||||
{C_setkeys, C_setkeys + " BASE64_keypair * Sets the keypair for the current nickname."},
|
||||
{C_setnick, C_setnick + " nickname * Create a new nickname."},
|
||||
{C_show, C_show + " * Display the status of the current nickname."},
|
||||
{C_show_props, C_show_props + " * Display the properties of the current nickname."},
|
||||
{C_start, C_start + " * Start the current nickname tunnel."},
|
||||
{C_status, C_status + " nickname * Display status of a nicknamed tunnel."},
|
||||
{C_stop, C_stop + " * Stops the current nicknamed tunnel."},
|
||||
{C_verify, C_verify + " BASE64_key * Verifies BASE64 destination."},
|
||||
{C_visit, C_visit + " * Thread dump to wrapper.log."},
|
||||
{C_zap, C_zap + " * Shuts down BOB."},
|
||||
{"", "COMMANDS: " + // this is ugly, but...
|
||||
C_help + " " +
|
||||
C_clear + " " +
|
||||
C_getdest + " " +
|
||||
C_getkeys + " " +
|
||||
C_getnick + " " +
|
||||
C_inhost + " " +
|
||||
C_inport + " " +
|
||||
C_list + " " +
|
||||
C_lookup + " " +
|
||||
C_newkeys + " " +
|
||||
C_option + " " +
|
||||
C_outhost + " " +
|
||||
C_outport + " " +
|
||||
C_quiet + " " +
|
||||
C_quit + " " +
|
||||
C_setkeys + " " +
|
||||
C_setnick + " " +
|
||||
C_show + " " +
|
||||
C_show_props + " " +
|
||||
C_start + " " +
|
||||
C_status + " " +
|
||||
C_stop + " " +
|
||||
C_verify + " " +
|
||||
C_visit + " " +
|
||||
C_zap
|
||||
},
|
||||
{" ", " "} // end of list
|
||||
};
|
||||
|
||||
/**
|
||||
* @param LIVE
|
||||
* @param server
|
||||
* @param props
|
||||
* @param database
|
||||
* @param _log
|
||||
*/
|
||||
DoCMDS(AtomicBoolean LIVE, AtomicBoolean lock, Socket server, Properties props, NamedDB database, Logger _log) {
|
||||
this.lock = lock;
|
||||
this.LIVE = LIVE;
|
||||
this.server = server;
|
||||
this.props = new Properties();
|
||||
this.database = database;
|
||||
this._log = _log;
|
||||
Lifted.copyProperties(props, this.props);
|
||||
}
|
||||
|
||||
private void rlock() {
|
||||
rlock(nickinfo);
|
||||
}
|
||||
|
||||
private void rlock(NamedDB Arg) {
|
||||
database.getReadLock();
|
||||
Arg.getReadLock();
|
||||
}
|
||||
|
||||
private void runlock() {
|
||||
runlock(nickinfo);
|
||||
}
|
||||
|
||||
private void runlock(NamedDB Arg) {
|
||||
Arg.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
}
|
||||
|
||||
private void wlock() {
|
||||
wlock(nickinfo);
|
||||
}
|
||||
|
||||
private void wlock(NamedDB Arg) {
|
||||
database.getWriteLock();
|
||||
Arg.getWriteLock();
|
||||
}
|
||||
|
||||
private void wunlock() {
|
||||
wunlock(nickinfo);
|
||||
}
|
||||
|
||||
private void wunlock(NamedDB Arg) {
|
||||
Arg.releaseWriteLock();
|
||||
database.releaseWriteLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to print info from the database
|
||||
*
|
||||
* @param out
|
||||
* @param info
|
||||
* @param key
|
||||
*/
|
||||
private void trypnt(PrintStream out, NamedDB info, String key) {
|
||||
rlock(info);
|
||||
try {
|
||||
out.print(" " + key + ": ");
|
||||
if (info.exists(key)) {
|
||||
out.print(info.get(key));
|
||||
} else {
|
||||
out.print("not_set");
|
||||
}
|
||||
} finally {
|
||||
runlock(info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print true or false if an object exists
|
||||
*
|
||||
* @param out
|
||||
* @param info
|
||||
* @param key
|
||||
*/
|
||||
private void tfpnt(PrintStream out, NamedDB info, String key) {
|
||||
rlock(info);
|
||||
try {
|
||||
out.print(" " + key + ": ");
|
||||
out.print(info.exists(key));
|
||||
} finally {
|
||||
runlock(info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error message
|
||||
*
|
||||
* @param out
|
||||
*/
|
||||
private static void nns(PrintStream out) {
|
||||
out.println("ERROR no nickname has been set");
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump various information from the database
|
||||
*
|
||||
* @param out
|
||||
* @param info
|
||||
*/
|
||||
private void nickprint(PrintStream out, NamedDB info) {
|
||||
trypnt(out, info, P_NICKNAME);
|
||||
trypnt(out, info, P_STARTING);
|
||||
trypnt(out, info, P_RUNNING);
|
||||
trypnt(out, info, P_STOPPING);
|
||||
tfpnt(out, info, P_KEYS);
|
||||
trypnt(out, info, P_QUIET);
|
||||
trypnt(out, info, P_INPORT);
|
||||
trypnt(out, info, P_INHOST);
|
||||
trypnt(out, info, P_OUTPORT);
|
||||
trypnt(out, info, P_OUTHOST);
|
||||
out.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump properties information from the database
|
||||
*
|
||||
* @param out
|
||||
* @param info
|
||||
*/
|
||||
private void propprint(PrintStream out, NamedDB info) {
|
||||
trypnt(out, info, P_PROPERTIES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print information on a specific record, indicated by NamedDB
|
||||
* @param out
|
||||
* @param Arg
|
||||
*/
|
||||
private void ttlpnt(PrintStream out, String Arg) {
|
||||
database.getReadLock();
|
||||
try {
|
||||
if (database.exists(Arg)) {
|
||||
out.print("DATA");
|
||||
nickprint(out, (NamedDB) database.get(Arg));
|
||||
}
|
||||
} finally {
|
||||
database.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this NamedDB's tunnel active?
|
||||
*
|
||||
* @param Arg
|
||||
* @return true if the tunnel is active
|
||||
*/
|
||||
private boolean tunnelactive(NamedDB Arg) {
|
||||
boolean retval;
|
||||
rlock(Arg);
|
||||
try {
|
||||
retval = (Arg.get(P_STARTING).equals(Boolean.TRUE) ||
|
||||
Arg.get(P_STOPPING).equals(Boolean.TRUE) ||
|
||||
Arg.get(P_RUNNING).equals(Boolean.TRUE));
|
||||
} finally {
|
||||
runlock();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the base64 information look OK
|
||||
*
|
||||
* @param data
|
||||
* @return OK
|
||||
*/
|
||||
private static boolean is64ok(String data) {
|
||||
try {
|
||||
new Destination(data);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual parser.
|
||||
* It probabbly needs a rewrite into functions, but I kind-of like inline code.
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
dk = ns = ip = op = false;
|
||||
try {
|
||||
try {
|
||||
// Get input from the client
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
|
||||
PrintStream out = new PrintStream(server.getOutputStream());
|
||||
quit:
|
||||
{
|
||||
die:
|
||||
{
|
||||
prikey = new ByteArrayOutputStream();
|
||||
out.println("BOB " + BOBversion);
|
||||
out.println("OK");
|
||||
while ((line = in.readLine()) != null) {
|
||||
StringTokenizer token = new StringTokenizer(line, " "); // use a space as a delimiter
|
||||
String Command = "";
|
||||
String Arg = "";
|
||||
NamedDB info;
|
||||
|
||||
if (token.countTokens() != 0) {
|
||||
Command = token.nextToken();
|
||||
Command =
|
||||
Command.toLowerCase(Locale.US);
|
||||
if (token.countTokens() != 0) {
|
||||
Arg = token.nextToken();
|
||||
} else {
|
||||
Arg = "";
|
||||
}
|
||||
// The rest of the tokens are considered junk,
|
||||
// and discarded without any warnings.
|
||||
if (Command.equals(C_help)) {
|
||||
for (int i = 0; !C_ALL[i][0].equals(" "); i++) {
|
||||
if (C_ALL[i][0].equalsIgnoreCase(Arg)) {
|
||||
out.println("OK " + C_ALL[i][1]);
|
||||
}
|
||||
}
|
||||
} else if (Command.equals(C_visit)) {
|
||||
visitAllThreads();
|
||||
out.println("OK ");
|
||||
} else if (Command.equals(C_lookup)) {
|
||||
Destination dest = null;
|
||||
String reply = null;
|
||||
if (Arg.endsWith(".i2p")) {
|
||||
try {
|
||||
//try {
|
||||
//dest = I2PTunnel.destFromName(Arg);
|
||||
//} catch (DataFormatException ex) {
|
||||
//}
|
||||
dest = I2PAppContext.getGlobalContext().namingService().lookup(Arg);
|
||||
if(dest != null) {
|
||||
reply = dest.toBase64();
|
||||
}
|
||||
} catch (NullPointerException npe) {
|
||||
// Could not find the destination!?
|
||||
}
|
||||
}
|
||||
if (reply == null) {
|
||||
out.println("ERROR Address Not found.");
|
||||
} else {
|
||||
out.println("OK " + reply);
|
||||
}
|
||||
} else if (Command.equals(C_getdest)) {
|
||||
if (ns) {
|
||||
if (dk) {
|
||||
rlock();
|
||||
try {
|
||||
out.println("OK " + nickinfo.get(P_DEST));
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
} finally {
|
||||
runlock();
|
||||
}
|
||||
} else {
|
||||
out.println("ERROR keys not set.");
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_list)) {
|
||||
// Produce a formatted list of all nicknames
|
||||
database.getReadLock();
|
||||
try {
|
||||
for (Object ndb : database.values()) {
|
||||
try {
|
||||
info = (NamedDB) ndb;
|
||||
out.print("DATA");
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
}
|
||||
nickprint(out, info);
|
||||
}
|
||||
} finally {
|
||||
database.releaseReadLock();
|
||||
}
|
||||
out.println("OK Listing done");
|
||||
} else if (Command.equals(C_quit)) {
|
||||
// End the command session
|
||||
break quit;
|
||||
} else if (Command.equals(C_zap)) {
|
||||
// Kill BOB!! (let's hope this works!)
|
||||
LIVE.set(false);
|
||||
// End the command session
|
||||
break quit;
|
||||
} else if (Command.equals(C_newkeys)) {
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
try {
|
||||
// Make a new PublicKey and PrivateKey
|
||||
prikey = new ByteArrayOutputStream();
|
||||
d = I2PClientFactory.createClient().createDestination(prikey);
|
||||
wlock();
|
||||
try {
|
||||
nickinfo.add(P_KEYS, prikey.toByteArray());
|
||||
nickinfo.add(P_DEST, d.toBase64());
|
||||
out.println("OK " + nickinfo.get(P_DEST));
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
dk = true;
|
||||
} catch (I2PException ipe) {
|
||||
_log.error("Error generating keys", ipe);
|
||||
out.println("ERROR generating keys");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_getkeys)) {
|
||||
// Return public key
|
||||
if (dk) {
|
||||
prikey = new ByteArrayOutputStream();
|
||||
rlock();
|
||||
try {
|
||||
prikey.write(((byte[]) nickinfo.get(P_KEYS)));
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
} finally {
|
||||
runlock();
|
||||
}
|
||||
out.println("OK " + net.i2p.data.Base64.encode(prikey.toByteArray()));
|
||||
} else {
|
||||
out.println("ERROR no public key has been set");
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_quiet)) {
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
wlock();
|
||||
try {
|
||||
nickinfo.add(P_QUIET, Boolean.valueOf(Arg));
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
out.println("OK Quiet set");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_verify)) {
|
||||
if (is64ok(Arg)) {
|
||||
out.println("OK");
|
||||
} else {
|
||||
out.println("ERROR not in BASE64 format");
|
||||
}
|
||||
} else if (Command.equals(C_setkeys)) {
|
||||
// Set the NamedDB to a privatekey in BASE64 format
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
try {
|
||||
prikey = new ByteArrayOutputStream();
|
||||
prikey.write(net.i2p.data.Base64.decode(Arg));
|
||||
d = new Destination();
|
||||
d.fromBase64(Arg);
|
||||
} catch (Exception ex) {
|
||||
Arg = "";
|
||||
}
|
||||
|
||||
if ((Arg.length() == 884) && is64ok(Arg)) {
|
||||
wlock();
|
||||
try {
|
||||
nickinfo.add(P_KEYS, prikey.toByteArray());
|
||||
nickinfo.add(P_DEST, d.toBase64());
|
||||
out.println("OK " + nickinfo.get(P_DEST));
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
dk = true;
|
||||
} else {
|
||||
out.println("ERROR not in BASE64 format");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_setnick)) {
|
||||
ns = dk = ip = op = false;
|
||||
database.getReadLock();
|
||||
try {
|
||||
nickinfo = (NamedDB) database.get(Arg);
|
||||
if (!tunnelactive(nickinfo)) {
|
||||
nickinfo = null;
|
||||
ns = true;
|
||||
}
|
||||
|
||||
} catch (Exception b) {
|
||||
nickinfo = null;
|
||||
ns = true;
|
||||
} finally {
|
||||
database.releaseReadLock();
|
||||
}
|
||||
// Clears and Sets the initial NamedDB structure to work with
|
||||
if (ns) {
|
||||
nickinfo = new NamedDB();
|
||||
wlock();
|
||||
try {
|
||||
database.add(Arg, nickinfo);
|
||||
nickinfo.add(P_NICKNAME, Arg);
|
||||
nickinfo.add(P_STARTING, Boolean.FALSE);
|
||||
nickinfo.add(P_RUNNING, Boolean.FALSE);
|
||||
nickinfo.add(P_STOPPING, Boolean.FALSE);
|
||||
nickinfo.add(P_QUIET, Boolean.FALSE);
|
||||
nickinfo.add(P_INHOST, "localhost");
|
||||
nickinfo.add(P_OUTHOST, "localhost");
|
||||
Properties Q = new Properties();
|
||||
Lifted.copyProperties(this.props, Q);
|
||||
Q.setProperty("inbound.nickname", Arg);
|
||||
Q.setProperty("outbound.nickname", Arg);
|
||||
nickinfo.add(P_PROPERTIES, Q);
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
out.println("OK Nickname set to " + Arg);
|
||||
} else {
|
||||
out.println("ERROR tunnel is active");
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_option)) {
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
StringTokenizer otoken = new StringTokenizer(Arg, "="); // use an equal sign as a delimiter
|
||||
if (otoken.countTokens() != 2) {
|
||||
out.println("ERROR too many or no options.");
|
||||
} else {
|
||||
String pname = otoken.nextToken();
|
||||
String pval = otoken.nextToken();
|
||||
wlock();
|
||||
try {
|
||||
Properties Q = (Properties) nickinfo.get(P_PROPERTIES);
|
||||
Q.setProperty(pname, pval);
|
||||
nickinfo.add(P_PROPERTIES, Q);
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
out.println("OK " + pname + " set to " + pval);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_getnick)) {
|
||||
// Get the NamedDB to work with...
|
||||
boolean nsfail = false;
|
||||
database.getReadLock();
|
||||
try {
|
||||
nickinfo = (NamedDB) database.get(Arg);
|
||||
ns = true;
|
||||
} catch (RuntimeException b) {
|
||||
nsfail = true;
|
||||
nns(out);
|
||||
} finally {
|
||||
database.releaseReadLock();
|
||||
}
|
||||
if (ns && !nsfail) {
|
||||
rlock();
|
||||
try {
|
||||
dk = nickinfo.exists(P_KEYS);
|
||||
ip = nickinfo.exists(P_INPORT);
|
||||
op = nickinfo.exists(P_OUTPORT);
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
} finally {
|
||||
runlock();
|
||||
}
|
||||
// Finally say OK.
|
||||
out.println("OK Nickname set to " + Arg);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_inport)) {
|
||||
// Set the NamedDB inbound TO the router port
|
||||
// app --> BOB
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
int prt;
|
||||
wlock();
|
||||
try {
|
||||
nickinfo.kill(P_INPORT);
|
||||
prt = Integer.parseInt(Arg);
|
||||
if (prt > 1 && prt < 65536) {
|
||||
try {
|
||||
nickinfo.add(P_INPORT, Integer.valueOf(prt));
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
}
|
||||
ip = nickinfo.exists(P_INPORT);
|
||||
} catch (NumberFormatException nfe) {
|
||||
out.println("ERROR not a number");
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
if (ip) {
|
||||
out.println("OK inbound port set");
|
||||
} else {
|
||||
out.println("ERROR port out of range");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_outport)) {
|
||||
// Set the NamedDB outbound FROM the router port
|
||||
// BOB --> app
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
int prt;
|
||||
wlock();
|
||||
try {
|
||||
nickinfo.kill(P_OUTPORT);
|
||||
prt = Integer.parseInt(Arg);
|
||||
if (prt > 1 && prt < 65536) {
|
||||
nickinfo.add(P_OUTPORT, Integer.valueOf(prt));
|
||||
}
|
||||
ip = nickinfo.exists(P_OUTPORT);
|
||||
} catch (NumberFormatException nfe) {
|
||||
out.println("ERROR not a number");
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
if (ip) {
|
||||
out.println("OK outbound port set");
|
||||
} else {
|
||||
out.println("ERROR port out of range");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_inhost)) {
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
wlock();
|
||||
try {
|
||||
nickinfo.add(P_INHOST, Arg);
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
out.println("OK inhost set");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_outhost)) {
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
wlock();
|
||||
try {
|
||||
nickinfo.add(P_OUTHOST, Arg);
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
out.println("OK outhost set");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_show)) {
|
||||
// Get the current NamedDB properties
|
||||
if (ns) {
|
||||
out.print("OK");
|
||||
nickprint(out, nickinfo);
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_show_props)) {
|
||||
// Get the current options properties
|
||||
if (ns) {
|
||||
out.print("OK");
|
||||
propprint(out, nickinfo);
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_start)) {
|
||||
// Start the tunnel, if we have all the information
|
||||
if (ns && dk && (ip || op)) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
MUXlisten tunnel;
|
||||
try {
|
||||
while (!lock.compareAndSet(false, true)) {
|
||||
// wait
|
||||
}
|
||||
tunnel = new MUXlisten(lock, database, nickinfo, _log);
|
||||
Thread t = new I2PAppThread(tunnel);
|
||||
t.start();
|
||||
// try {
|
||||
// Thread.sleep(1000 * 10); // Slow down the startup.
|
||||
// } catch(InterruptedException ie) {
|
||||
// // ignore it
|
||||
// }
|
||||
out.println("OK tunnel starting");
|
||||
} catch (I2PException e) {
|
||||
lock.set(false);
|
||||
out.println("ERROR starting tunnel: " + e);
|
||||
} catch (IOException e) {
|
||||
lock.set(false);
|
||||
out.println("ERROR starting tunnel: " + e);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
|
||||
} else {
|
||||
out.println("ERROR tunnel settings incomplete");
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_stop)) {
|
||||
// Stop the tunnel, if it is running
|
||||
if (ns) {
|
||||
rlock();
|
||||
boolean released = false;
|
||||
try {
|
||||
if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
|
||||
runlock();
|
||||
released = true;
|
||||
wlock();
|
||||
try {
|
||||
nickinfo.add(P_STOPPING, Boolean.TRUE);
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
out.println("OK tunnel stopping");
|
||||
} else {
|
||||
out.println("ERROR tunnel is inactive");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
} finally {
|
||||
if (!released)
|
||||
runlock();
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_clear)) {
|
||||
// Clear use of the NamedDB if stopped
|
||||
if (ns) {
|
||||
try {
|
||||
if (tunnelactive(nickinfo)) {
|
||||
out.println("ERROR tunnel is active");
|
||||
} else {
|
||||
database.getWriteLock();
|
||||
try {
|
||||
database.kill((String) nickinfo.get(P_NICKNAME));
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
database.releaseWriteLock();
|
||||
}
|
||||
dk = ns = ip = op = false;
|
||||
out.println("OK cleared");
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
|
||||
} else if (Command.equals(C_status)) {
|
||||
database.getReadLock();
|
||||
try {
|
||||
if (database.exists(Arg)) {
|
||||
// Show status of a NamedDB
|
||||
out.print("OK ");
|
||||
try {
|
||||
ttlpnt(out, Arg);
|
||||
} catch (Exception e) {
|
||||
out.println(); // this will cause an IOE if IOE
|
||||
break die;
|
||||
}
|
||||
} else {
|
||||
nns(out);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
} finally {
|
||||
database.releaseReadLock();
|
||||
}
|
||||
} else {
|
||||
out.println("ERROR UNKNOWN COMMAND! Try help");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // die
|
||||
out.print("ERROR A really bad error just happened, ");
|
||||
} // quit
|
||||
// Say goodbye.
|
||||
|
||||
out.println("OK Bye!");
|
||||
|
||||
} catch (IOException ioe) {
|
||||
// not really needed, except to debug.
|
||||
// BOB.warn("IOException on socket listen: " + ioe);
|
||||
// ioe.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
server.close();
|
||||
} catch (IOException ex) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
}
|
||||
// Debugging... None of this is normally used.
|
||||
|
||||
/**
|
||||
* Find the root thread group and print them all.
|
||||
*
|
||||
*/
|
||||
private void visitAllThreads() {
|
||||
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
|
||||
while (root.getParent() != null) {
|
||||
root = root.getParent();
|
||||
}
|
||||
|
||||
// Visit each thread group
|
||||
visit(root, 0, root.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively visits all thread groups under `group' and dumps them.
|
||||
* @param group ThreadGroup to visit
|
||||
* @param level Current level
|
||||
*/
|
||||
private static void visit(ThreadGroup group, int level, String tn) {
|
||||
// Get threads in `group'
|
||||
int numThreads = group.activeCount();
|
||||
Thread[] threads = new Thread[numThreads * 2];
|
||||
numThreads = group.enumerate(threads, false);
|
||||
String indent = "------------------------------------".substring(0, level) + "-> ";
|
||||
// Enumerate each thread in `group' and print it.
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
// Get thread
|
||||
Thread thread = threads[i];
|
||||
System.out.println("BOB: " + indent + tn + ": " + thread.toString());
|
||||
}
|
||||
|
||||
// Get thread subgroups of `group'
|
||||
int numGroups = group.activeGroupCount();
|
||||
ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
|
||||
numGroups = group.enumerate(groups, false);
|
||||
|
||||
// Recursively visit each subgroup
|
||||
for (int i = 0; i < numGroups; i++) {
|
||||
visit(groups[i], level + 1, groups[i].getName());
|
||||
}
|
||||
}
|
||||
}
|
99
apps/BOB/src/net/i2p/BOB/I2Plistener.java
Normal file
99
apps/BOB/src/net/i2p/BOB/I2Plistener.java
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
* Listen on I2P and connect to TCP
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class I2Plistener implements Runnable {
|
||||
|
||||
private final NamedDB info, database;
|
||||
private final Logger _log;
|
||||
private final I2PServerSocket serverSocket;
|
||||
private final AtomicBoolean lives;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param SS
|
||||
* @param S unused
|
||||
* @param info
|
||||
* @param database
|
||||
* @param _log
|
||||
*/
|
||||
I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Logger _log, AtomicBoolean lives) {
|
||||
this.database = database;
|
||||
this.info = info;
|
||||
this._log = _log;
|
||||
this.serverSocket = SS;
|
||||
this.lives = lives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply listen on I2P port, and thread connections
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
boolean g = false;
|
||||
I2PSocket sessSocket = null;
|
||||
int conn = 0;
|
||||
try {
|
||||
try {
|
||||
serverSocket.setSoTimeout(50);
|
||||
|
||||
while (lives.get()) {
|
||||
try {
|
||||
sessSocket = serverSocket.accept();
|
||||
g = true;
|
||||
} catch (ConnectException ce) {
|
||||
g = false;
|
||||
} catch (SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
if (g) {
|
||||
g = false;
|
||||
conn++;
|
||||
// toss the connection to a new thread.
|
||||
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
|
||||
Thread t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
|
||||
t.start();
|
||||
}
|
||||
|
||||
}
|
||||
} catch (I2PException e) {
|
||||
// bad stuff
|
||||
System.out.println("Exception " + e);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (I2PException ex) {
|
||||
}
|
||||
// System.out.println("I2Plistener: Close");
|
||||
}
|
||||
}
|
||||
}
|
169
apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
Normal file
169
apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
Normal file
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
* Process I2P->TCP
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class I2PtoTCP implements Runnable {
|
||||
|
||||
private I2PSocket I2P;
|
||||
private final NamedDB info, database;
|
||||
private Socket sock;
|
||||
private final AtomicBoolean lives;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param I2Psock
|
||||
* @param info
|
||||
* @param database
|
||||
*/
|
||||
I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database, AtomicBoolean lives) {
|
||||
this.I2P = I2Psock;
|
||||
this.info = info;
|
||||
this.database = database;
|
||||
this.lives = lives;
|
||||
}
|
||||
|
||||
private void rlock() {
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
}
|
||||
|
||||
private void runlock() {
|
||||
info.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* I2P stream to TCP stream thread starter
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
String host;
|
||||
int port;
|
||||
boolean tell;
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
InputStream Iin = null;
|
||||
OutputStream Iout = null;
|
||||
Thread t = null;
|
||||
Thread q = null;
|
||||
try {
|
||||
die:
|
||||
{
|
||||
try {
|
||||
rlock();
|
||||
try {
|
||||
host = info.get("OUTHOST").toString();
|
||||
port = Integer.parseInt(info.get("OUTPORT").toString());
|
||||
tell = info.get("QUIET").equals(Boolean.FALSE);
|
||||
} catch (Exception e) {
|
||||
break die;
|
||||
} finally {
|
||||
runlock();
|
||||
}
|
||||
sock = new Socket(host, port);
|
||||
sock.setKeepAlive(true);
|
||||
// make readers/writers
|
||||
in = sock.getInputStream();
|
||||
out = sock.getOutputStream();
|
||||
Iin = I2P.getInputStream();
|
||||
Iout = I2P.getOutputStream();
|
||||
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
|
||||
|
||||
if (tell) {
|
||||
// tell who is connecting
|
||||
out.write(DataHelper.getASCII(I2P.getPeerDestination().toBase64()));
|
||||
out.write(10); // nl
|
||||
out.flush(); // not really needed, but...
|
||||
}
|
||||
// setup to cross the streams
|
||||
TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
|
||||
TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
|
||||
t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA");
|
||||
q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB");
|
||||
// Fire!
|
||||
t.start();
|
||||
q.start();
|
||||
while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
|
||||
try {
|
||||
Thread.sleep(10); //sleep for 10 ms
|
||||
} catch (InterruptedException e) {
|
||||
break die;
|
||||
}
|
||||
}
|
||||
// System.out.println("I2PtoTCP: Going away...");
|
||||
} catch (Exception e) {
|
||||
// System.out.println("I2PtoTCP: Owch! damn!");
|
||||
break die;
|
||||
}
|
||||
} // die
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try {
|
||||
out.close();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try {
|
||||
Iin.close();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try {
|
||||
Iout.close();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try {
|
||||
t.interrupt();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
q.interrupt();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
// System.out.println("I2PtoTCP: Close I2P");
|
||||
I2P.close();
|
||||
} catch (Exception e) {
|
||||
tell = false;
|
||||
}
|
||||
//System.out.println("I2PtoTCP: Closed I2P");
|
||||
try {
|
||||
// System.out.println("I2PtoTCP: Close sock");
|
||||
sock.close();
|
||||
} catch (Exception e) {
|
||||
tell = false;
|
||||
}
|
||||
// System.out.println("I2PtoTCP: Done");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
46
apps/BOB/src/net/i2p/BOB/Lifted.java
Normal file
46
apps/BOB/src/net/i2p/BOB/Lifted.java
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Sets of "friendly" utilities to make life easier.
|
||||
* Any "Lifted" code will apear here, and credits given.
|
||||
* It's better to "Lift" a small chunk of "free" code than add in piles of
|
||||
* code we don't need, and don't want.
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class Lifted {
|
||||
|
||||
/**
|
||||
* Copy a set of properties from one Property to another.
|
||||
* Lifted from Apache Derby code svn repository.
|
||||
* Liscenced as follows:
|
||||
* http://svn.apache.org/repos/asf/db/derby/code/trunk/LICENSE
|
||||
*
|
||||
* @param src_prop Source set of properties to copy from.
|
||||
* @param dest_prop Dest Properties to copy into.
|
||||
*
|
||||
**/
|
||||
public static void copyProperties(Properties src_prop, Properties dest_prop) {
|
||||
for (Map.Entry<Object, Object> e : src_prop.entrySet()) {
|
||||
dest_prop.put((String)e.getKey(), (String)e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
44
apps/BOB/src/net/i2p/BOB/Logger.java
Normal file
44
apps/BOB/src/net/i2p/BOB/Logger.java
Normal file
@ -0,0 +1,44 @@
|
||||
package net.i2p.BOB;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
|
||||
public class Logger {
|
||||
public Log log;
|
||||
private boolean logToStdout;
|
||||
|
||||
public Logger(Log log, boolean logToStdout) {
|
||||
this.log = log;
|
||||
this.logToStdout = logToStdout;
|
||||
}
|
||||
|
||||
public void info(String msg) {
|
||||
if (logToStdout)
|
||||
System.out.println("INFO: " + msg);
|
||||
if (log.shouldLog(Log.INFO))
|
||||
log.info(msg);
|
||||
}
|
||||
|
||||
public void warn(String msg) {
|
||||
warn(msg, null);
|
||||
}
|
||||
|
||||
public void warn(String msg, Throwable e) {
|
||||
if (logToStdout) {
|
||||
System.out.println("WARNING: " + msg);
|
||||
if (e != null)
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (log.shouldLog(Log.WARN))
|
||||
log.warn(msg, e);
|
||||
}
|
||||
|
||||
public void error(String msg, Throwable e) {
|
||||
if (logToStdout) {
|
||||
System.out.println("ERROR: " + msg);
|
||||
if (e != null)
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (log.shouldLog(Log.ERROR))
|
||||
log.error(msg, e);
|
||||
}
|
||||
}
|
416
apps/BOB/src/net/i2p/BOB/MUXlisten.java
Normal file
416
apps/BOB/src/net/i2p/BOB/MUXlisten.java
Normal file
@ -0,0 +1,416 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
* Multiplex listeners for TCP and I2P
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class MUXlisten implements Runnable {
|
||||
|
||||
private final NamedDB database, info;
|
||||
private final Logger _log;
|
||||
private final I2PSocketManager socketManager;
|
||||
private final ByteArrayInputStream prikey;
|
||||
private ThreadGroup tg;
|
||||
private final String N;
|
||||
private ServerSocket listener;
|
||||
private static final int backlog = 50; // should this be more? less?
|
||||
private final boolean go_out;
|
||||
private final boolean come_in;
|
||||
private final AtomicBoolean lock;
|
||||
private final AtomicBoolean lives;
|
||||
|
||||
/**
|
||||
* Constructor Will fail if INPORT is occupied.
|
||||
*
|
||||
* @param info DB entry for this tunnel
|
||||
* @param database master database of tunnels
|
||||
* @param _log
|
||||
* @throws net.i2p.I2PException
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
MUXlisten(AtomicBoolean lock, NamedDB database, NamedDB info, Logger _log) throws I2PException, IOException, RuntimeException {
|
||||
int port = 0;
|
||||
InetAddress host = null;
|
||||
this.lock = lock;
|
||||
this.tg = null;
|
||||
this.database = database;
|
||||
this.info = info;
|
||||
this._log = _log;
|
||||
lives = new AtomicBoolean(false);
|
||||
try {
|
||||
wlock();
|
||||
try {
|
||||
this.info.add("STARTING", Boolean.TRUE);
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
Properties Q = new Properties();
|
||||
rlock();
|
||||
try {
|
||||
N = this.info.get("NICKNAME").toString();
|
||||
prikey = new ByteArrayInputStream((byte[]) info.get("KEYS"));
|
||||
// Make a new copy so that anything else won't muck with our database.
|
||||
Properties R = (Properties) info.get("PROPERTIES");
|
||||
Lifted.copyProperties(R, Q);
|
||||
|
||||
this.go_out = info.exists("OUTPORT");
|
||||
this.come_in = info.exists("INPORT");
|
||||
if (this.come_in) {
|
||||
port = Integer.parseInt(info.get("INPORT").toString());
|
||||
host = InetAddress.getByName(info.get("INHOST").toString());
|
||||
}
|
||||
} finally {
|
||||
runlock();
|
||||
}
|
||||
|
||||
String i2cpHost = Q.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
|
||||
int i2cpPort = I2PClient.DEFAULT_LISTEN_PORT;
|
||||
String i2cpPortStr = Q.getProperty(I2PClient.PROP_TCP_PORT);
|
||||
if (i2cpPortStr != null) {
|
||||
try {
|
||||
i2cpPort = Integer.parseInt(i2cpPortStr);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new IllegalArgumentException("Invalid I2CP port specified [" + i2cpPortStr + "]");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.come_in) {
|
||||
this.listener = new ServerSocket(port, backlog, host);
|
||||
}
|
||||
socketManager = I2PSocketManagerFactory.createManager(
|
||||
prikey, i2cpHost, i2cpPort, Q);
|
||||
} catch (IOException e) {
|
||||
// Something went bad.
|
||||
wlock();
|
||||
try {
|
||||
this.info.add("STARTING", Boolean.FALSE);
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
// Something went bad.
|
||||
wlock();
|
||||
try {
|
||||
this.info.add("STARTING", Boolean.FALSE);
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
// Something else went bad.
|
||||
wlock();
|
||||
try {
|
||||
this.info.add("STARTING", Boolean.FALSE);
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void rlock() {
|
||||
database.getReadLock();
|
||||
info.getReadLock();
|
||||
}
|
||||
|
||||
private void runlock() {
|
||||
info.releaseReadLock();
|
||||
database.releaseReadLock();
|
||||
}
|
||||
|
||||
private void wlock() {
|
||||
database.getWriteLock();
|
||||
info.getWriteLock();
|
||||
}
|
||||
|
||||
private void wunlock() {
|
||||
info.releaseWriteLock();
|
||||
database.releaseWriteLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* MUX sockets, fire off a thread to connect, get destination info, and do I/O
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
I2PServerSocket SS = null;
|
||||
Thread t = null;
|
||||
Thread q = null;
|
||||
try {
|
||||
wlock();
|
||||
try {
|
||||
try {
|
||||
info.add("RUNNING", Boolean.TRUE);
|
||||
} catch (Exception e) {
|
||||
lock.set(false);
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
lock.set(false);
|
||||
return;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
lives.set(true);
|
||||
lock.set(false);
|
||||
quit:
|
||||
{
|
||||
try {
|
||||
tg = new ThreadGroup(N);
|
||||
{
|
||||
// toss the connections to a new threads.
|
||||
// will wrap with TCP and UDP when UDP works
|
||||
|
||||
if (go_out) {
|
||||
// I2P -> TCP
|
||||
SS = socketManager.getServerSocket();
|
||||
I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log, lives);
|
||||
t = new I2PAppThread(tg, conn, "BOBI2Plistener " + N);
|
||||
t.start();
|
||||
}
|
||||
|
||||
if (come_in) {
|
||||
// TCP -> I2P
|
||||
TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log, lives);
|
||||
q = new I2PAppThread(tg, conn, "BOBTCPlistener " + N);
|
||||
q.start();
|
||||
}
|
||||
|
||||
wlock();
|
||||
try {
|
||||
try {
|
||||
info.add("STARTING", Boolean.FALSE);
|
||||
} catch (Exception e) {
|
||||
break quit;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break quit;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
boolean spin = true;
|
||||
while (spin && lives.get()) {
|
||||
try {
|
||||
Thread.sleep(1000); //sleep for 1 second
|
||||
} catch (InterruptedException e) {
|
||||
break quit;
|
||||
}
|
||||
rlock();
|
||||
try {
|
||||
try {
|
||||
spin = info.get("STOPPING").equals(Boolean.FALSE);
|
||||
} catch (Exception e) {
|
||||
break quit;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break quit;
|
||||
} finally {
|
||||
runlock();
|
||||
}
|
||||
}
|
||||
} // die
|
||||
|
||||
} catch (Exception e) {
|
||||
// System.out.println("MUXlisten: Caught an exception" + e);
|
||||
break quit;
|
||||
}
|
||||
} // quit
|
||||
} finally {
|
||||
lives.set(false);
|
||||
// Some grace time.
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
try {
|
||||
wlock();
|
||||
try {
|
||||
info.add("STARTING", Boolean.FALSE);
|
||||
info.add("STOPPING", Boolean.TRUE);
|
||||
info.add("RUNNING", Boolean.FALSE);
|
||||
} catch (Exception e) {
|
||||
lock.set(false);
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
// Start cleanup.
|
||||
while (!lock.compareAndSet(false, true)) {
|
||||
// wait
|
||||
}
|
||||
if (SS != null) {
|
||||
try {
|
||||
SS.close();
|
||||
} catch (I2PException ex) {
|
||||
}
|
||||
}
|
||||
if (listener != null) {
|
||||
try {
|
||||
listener.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Some grace time.
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
|
||||
// Hopefully nuke stuff here...
|
||||
{
|
||||
String groupName = tg.getName();
|
||||
try {
|
||||
_log.warn("destroySocketManager " + groupName);
|
||||
socketManager.destroySocketManager();
|
||||
_log.warn("destroySocketManager Successful" + groupName);
|
||||
} catch (Exception e) {
|
||||
// nop
|
||||
_log.warn("destroySocketManager Failed" + groupName);
|
||||
_log.warn(e.toString());
|
||||
}
|
||||
}
|
||||
// zero out everything.
|
||||
try {
|
||||
wlock();
|
||||
try {
|
||||
info.add("STARTING", Boolean.FALSE);
|
||||
info.add("STOPPING", Boolean.FALSE);
|
||||
info.add("RUNNING", Boolean.FALSE);
|
||||
} catch (Exception e) {
|
||||
lock.set(false);
|
||||
return;
|
||||
} finally {
|
||||
wunlock();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
lock.set(false); // Should we force waiting for all threads??
|
||||
|
||||
// Wait around till all threads are collected.
|
||||
if (tg != null) {
|
||||
String groupName = tg.getName();
|
||||
// System.out.println("BOB: MUXlisten: Starting thread collection for: " + groupName);
|
||||
_log.warn("BOB: MUXlisten: Starting thread collection for: " + groupName);
|
||||
if (tg.activeCount() + tg.activeGroupCount() != 0) {
|
||||
// visit(tg, 0, groupName);
|
||||
int foo = tg.activeCount() + tg.activeGroupCount();
|
||||
// hopefully no longer needed!
|
||||
// int bar = lives;
|
||||
// System.out.println("BOB: MUXlisten: Waiting on threads for " + groupName);
|
||||
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + groupName);
|
||||
// visit(tg, 0, groupName);
|
||||
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + groupName + "\n");
|
||||
// Happily spin forever :-(
|
||||
while (foo != 0) {
|
||||
foo = tg.activeCount() + tg.activeGroupCount();
|
||||
// if (lives != bar && lives != 0) {
|
||||
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + groupName);
|
||||
// visit(tg, 0, groupName);
|
||||
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + groupName + "\n");
|
||||
// }
|
||||
// bar = lives;
|
||||
try {
|
||||
Thread.sleep(100); //sleep for 100 ms (One tenth second)
|
||||
} catch (InterruptedException ex) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
}
|
||||
// System.out.println("BOB: MUXlisten: Threads went away. Success: " + groupName);
|
||||
_log.warn("BOB: MUXlisten: Threads went away. Success: " + groupName);
|
||||
tg.destroy();
|
||||
// Zap reference to the ThreadGroup so the JVM can GC it.
|
||||
tg = null;
|
||||
}
|
||||
try {
|
||||
socketManager.destroySocketManager();
|
||||
} catch (Exception e) {
|
||||
// nop
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Debugging... None of this is normally used.
|
||||
/**
|
||||
* Find the root thread group and print them all.
|
||||
*
|
||||
*/
|
||||
private void visitAllThreads() {
|
||||
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
|
||||
while (root.getParent() != null) {
|
||||
root = root.getParent();
|
||||
}
|
||||
|
||||
// Visit each thread group
|
||||
visit(root, 0, root.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively visits all thread groups under `group' and dumps them.
|
||||
* @param group ThreadGroup to visit
|
||||
* @param level Current level
|
||||
*/
|
||||
private static void visit(ThreadGroup group, int level, String tn) {
|
||||
// Get threads in `group'
|
||||
int numThreads = group.activeCount();
|
||||
Thread[] threads = new Thread[numThreads * 2];
|
||||
numThreads = group.enumerate(threads, false);
|
||||
String indent = "------------------------------------".substring(0, level) + "-> ";
|
||||
// Enumerate each thread in `group' and print it.
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
// Get thread
|
||||
Thread thread = threads[i];
|
||||
System.out.println("BOB: MUXlisten: " + tn + ": " + indent + thread.toString());
|
||||
}
|
||||
|
||||
// Get thread subgroups of `group'
|
||||
int numGroups = group.activeGroupCount();
|
||||
ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
|
||||
numGroups = group.enumerate(groups, false);
|
||||
|
||||
// Recursively visit each subgroup
|
||||
for (int i = 0; i < numGroups; i++) {
|
||||
visit(groups[i], level + 1, groups[i].getName());
|
||||
}
|
||||
}
|
||||
}
|
39
apps/BOB/src/net/i2p/BOB/Main.java
Normal file
39
apps/BOB/src/net/i2p/BOB/Main.java
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import net.i2p.util.SimpleTimer2;
|
||||
|
||||
/**
|
||||
* Start from command line
|
||||
*
|
||||
* @author sponge
|
||||
*
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
/**
|
||||
* @param args the command line arguments, these are not used yet
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// THINK THINK THINK THINK THINK THINK
|
||||
SimpleTimer2 Y2 = SimpleTimer2.getInstance();
|
||||
|
||||
BOB.main(args);
|
||||
|
||||
Y2.stop();
|
||||
}
|
||||
}
|
106
apps/BOB/src/net/i2p/BOB/NamedDB.java
Normal file
106
apps/BOB/src/net/i2p/BOB/NamedDB.java
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
|
||||
/**
|
||||
* Internal database to relate nicknames to options to values
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class NamedDB {
|
||||
|
||||
private final Map<String, Object> data;
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public NamedDB() {
|
||||
this.data = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
public void getReadLock() {
|
||||
lock.readLock().lock();
|
||||
}
|
||||
|
||||
public void releaseReadLock() {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
|
||||
public void getWriteLock() {
|
||||
lock.writeLock().lock();
|
||||
}
|
||||
|
||||
public void releaseWriteLock() {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an object if it exists
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public void kill(String key) {
|
||||
data.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add object, deletes the old one if it exists
|
||||
*
|
||||
* @param key
|
||||
* @param val
|
||||
*/
|
||||
public void add(String key, Object val) {
|
||||
data.put(key, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object, and return it, throws RuntimeException if not found
|
||||
*
|
||||
* @param key non-null
|
||||
* @return Object non-null
|
||||
* @throws java.lang.RuntimeException if not found
|
||||
*/
|
||||
public Object get(String key) throws RuntimeException {
|
||||
Object rv = data.get(key);
|
||||
if (rv != null)
|
||||
return rv;
|
||||
throw new RuntimeException("Key not found");
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if an object exists, else returns false
|
||||
*
|
||||
* @param key
|
||||
* @return true if an object exists, else returns false
|
||||
*/
|
||||
public boolean exists(String key) {
|
||||
return data.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.29 replaces getcount() and getnext(int)
|
||||
*/
|
||||
public Collection<Object> values() {
|
||||
return data.values();
|
||||
}
|
||||
}
|
121
apps/BOB/src/net/i2p/BOB/TCPio.java
Normal file
121
apps/BOB/src/net/i2p/BOB/TCPio.java
Normal file
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Shove data from one stream to the other.
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class TCPio implements Runnable {
|
||||
|
||||
private final InputStream Ain;
|
||||
private final OutputStream Aout;
|
||||
private final AtomicBoolean lives;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Ain InputStream
|
||||
* @param Aout OutputStream
|
||||
*
|
||||
* param database
|
||||
*/
|
||||
TCPio(InputStream Ain, OutputStream Aout, AtomicBoolean lives) {
|
||||
this.Ain = Ain;
|
||||
this.Aout = Aout;
|
||||
this.lives = lives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy from source to destination...
|
||||
* and yes, we are totally OK to block here on writes,
|
||||
* The OS has buffers, and I intend to use them.
|
||||
* We send an interrupt signal to the threadgroup to
|
||||
* unwedge any pending writes.
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
/*
|
||||
* NOTE:
|
||||
* The write method of OutputStream calls the write method of
|
||||
* one argument on each of the bytes to be written out.
|
||||
* Subclasses are encouraged to override this method and provide
|
||||
* a more efficient implementation.
|
||||
*
|
||||
* So, is this really a performance problem?
|
||||
* Should we expand to several bytes?
|
||||
* I don't believe there would be any gain, since read method
|
||||
* has the same reccomendations. If anyone has a better way to
|
||||
* do this, I'm interested in performance improvements.
|
||||
*
|
||||
* --Sponge
|
||||
*
|
||||
* Tested with 128 bytes, and there was no performance gain.
|
||||
* 8192 bytes did lower load average across many connections.
|
||||
* Should I raise it higer? The correct thing to do would be to
|
||||
* override... perhaps use NTCP, but I2P's streaming lib lacks
|
||||
* anything NTCP compatable.
|
||||
*
|
||||
* --Sponge
|
||||
*/
|
||||
|
||||
int b;
|
||||
byte a[] = new byte[8192];
|
||||
try {
|
||||
try {
|
||||
while (lives.get()) {
|
||||
b = Ain.read(a, 0, 8192);
|
||||
if (b > 0) {
|
||||
Aout.write(a, 0, b);
|
||||
} else if (b == 0) {
|
||||
while(Ain.available() == 0) {
|
||||
Thread.sleep(20);
|
||||
}
|
||||
} else {
|
||||
/* according to the specs:
|
||||
*
|
||||
* The total number of bytes read into the buffer,
|
||||
* or -1 if there is no more data because the end of
|
||||
* the stream has been reached.
|
||||
*
|
||||
*/
|
||||
// System.out.println("TCPio: End Of Stream");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
// System.out.println("TCPio: Leaving.");
|
||||
} finally {
|
||||
// Eject!!! Eject!!!
|
||||
//System.out.println("TCPio: Caught an exception " + e);
|
||||
try {
|
||||
Ain.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
try {
|
||||
Aout.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
95
apps/BOB/src/net/i2p/BOB/TCPlistener.java
Normal file
95
apps/BOB/src/net/i2p/BOB/TCPlistener.java
Normal file
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
* Listen on TCP port and connect to I2P
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class TCPlistener implements Runnable {
|
||||
|
||||
private final NamedDB info, database;
|
||||
private final Logger _log;
|
||||
private final I2PSocketManager socketManager;
|
||||
private final ServerSocket listener;
|
||||
private final AtomicBoolean lives;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param S
|
||||
* @param info
|
||||
* @param database
|
||||
* @param _log
|
||||
*/
|
||||
TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Logger _log, AtomicBoolean lives) {
|
||||
this.database = database;
|
||||
this.info = info;
|
||||
this._log = _log;
|
||||
this.socketManager = S;
|
||||
this.listener = listener;
|
||||
this.lives = lives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply listen on TCP port, and thread connections
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
boolean g = false;
|
||||
int conn = 0;
|
||||
Socket server = null;
|
||||
try {
|
||||
try {
|
||||
listener.setSoTimeout(50); // We don't block, we cycle and check.
|
||||
while (lives.get()) {
|
||||
try {
|
||||
server = listener.accept();
|
||||
server.setKeepAlive(true);
|
||||
g = true;
|
||||
} catch (SocketTimeoutException ste) {
|
||||
g = false;
|
||||
}
|
||||
if (g) {
|
||||
conn++;
|
||||
// toss the connection to a new thread.
|
||||
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
|
||||
Thread t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
|
||||
t.start();
|
||||
g = false;
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
listener.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
//System.out.println("TCPlistener: " + Thread.currentThread().getName() + "Done.");
|
||||
}
|
||||
}
|
||||
}
|
222
apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
Normal file
222
apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
Normal file
@ -0,0 +1,222 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.net.Socket;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
*
|
||||
* Process TCP->I2P
|
||||
*
|
||||
* @author sponge
|
||||
*/
|
||||
public class TCPtoI2P implements Runnable {
|
||||
|
||||
private I2PSocket I2P;
|
||||
private final Socket sock;
|
||||
private final I2PSocketManager socketManager;
|
||||
private final AtomicBoolean lives;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param i2p
|
||||
* @param socket
|
||||
* @param info unused
|
||||
* @param database unused
|
||||
*/
|
||||
TCPtoI2P(I2PSocketManager i2p, Socket socket, NamedDB info, NamedDB database, AtomicBoolean lives) {
|
||||
this.sock = socket;
|
||||
this.socketManager = i2p;
|
||||
this.lives = lives;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a more forgiving readline,
|
||||
* it works on unbuffered streams
|
||||
*
|
||||
* @param in
|
||||
* @return line of text as a String
|
||||
* @throws IOException
|
||||
*/
|
||||
private static String lnRead(InputStream in) throws IOException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int b;
|
||||
char c;
|
||||
|
||||
while (true) {
|
||||
b = in.read();
|
||||
if (b == 13) {
|
||||
//skip CR
|
||||
continue;
|
||||
}
|
||||
if (b < 20 || b > 126) {
|
||||
// exit on anything not legal
|
||||
break;
|
||||
}
|
||||
c = (char) (b & 0x7f); // We only care about ASCII
|
||||
builder.append(c);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error message to out
|
||||
*
|
||||
* @param e
|
||||
* @param out
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
private void Emsg(String e, OutputStream out) throws IOException {
|
||||
// Debugging System.out.println("ERROR TCPtoI2P: " + e);
|
||||
out.write("ERROR ".concat(e).getBytes("UTF-8"));
|
||||
out.write(13);
|
||||
out.write(10);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* TCP stream to I2P stream thread starter
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
String line, input;
|
||||
InputStream Iin = null;
|
||||
OutputStream Iout = null;
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
Thread t = null;
|
||||
Thread q = null;
|
||||
try {
|
||||
try {
|
||||
|
||||
in = sock.getInputStream();
|
||||
out = sock.getOutputStream();
|
||||
line = lnRead(in);
|
||||
input = line.toLowerCase(Locale.US);
|
||||
Destination dest = null;
|
||||
if (input.endsWith(".i2p")) {
|
||||
//dest = I2PTunnel.destFromName(input);
|
||||
dest = I2PAppContext.getGlobalContext().namingService().lookup(input);
|
||||
if (dest != null) {
|
||||
line = dest.toBase64();
|
||||
} else {
|
||||
Emsg("Can't find destination: " + input, out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
dest = new Destination();
|
||||
dest.fromBase64(line);
|
||||
|
||||
try {
|
||||
// get a client socket
|
||||
I2P = socketManager.connect(dest);
|
||||
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
|
||||
// make readers/writers
|
||||
Iin = I2P.getInputStream();
|
||||
Iout = I2P.getOutputStream();
|
||||
// setup to cross the streams
|
||||
TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
|
||||
TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
|
||||
t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA");
|
||||
q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB");
|
||||
// Fire!
|
||||
t.start();
|
||||
q.start();
|
||||
while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
|
||||
Thread.sleep(10); //sleep for 10 ms
|
||||
}
|
||||
} catch (I2PException e) {
|
||||
Emsg(e.toString(), out);
|
||||
} catch (ConnectException e) {
|
||||
Emsg(e.toString(), out);
|
||||
} catch (NoRouteToHostException e) {
|
||||
Emsg(e.toString(), out);
|
||||
}
|
||||
|
||||
} catch (InterruptedIOException e) {
|
||||
// We're breaking away.
|
||||
} catch (InterruptedException e) {
|
||||
// ditto
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
Emsg(e.toString(), out);
|
||||
} catch (IOException ex) {
|
||||
// ditto
|
||||
}
|
||||
} catch (DataFormatException e) {
|
||||
try {
|
||||
Emsg(e.toString(), out);
|
||||
} catch (IOException ex) {
|
||||
// ditto
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
try {
|
||||
t.interrupt();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
q.interrupt();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
in.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
Iin.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
Iout.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
// System.out.println("TCPtoI2P: Close I2P");
|
||||
I2P.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
try {
|
||||
// System.out.println("TCPtoI2P: Close sock");
|
||||
sock.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
// System.out.println("TCPtoI2P: Done.");
|
||||
}
|
||||
}
|
140
apps/BOB/src/net/i2p/BOB/UDPIOthread.java
Normal file
140
apps/BOB/src/net/i2p/BOB/UDPIOthread.java
Normal file
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* WTFPL
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* Copyright (C) sponge
|
||||
* Planet Earth
|
||||
*
|
||||
* See...
|
||||
*
|
||||
* http://sam.zoy.org/wtfpl/
|
||||
* and
|
||||
* http://en.wikipedia.org/wiki/WTFPL
|
||||
*
|
||||
* ...for any additional details and license questions.
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.I2PSessionListener;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* UDP IO on I2P
|
||||
*
|
||||
* FIX ME: Untested, and incomplete!
|
||||
* I have no personal need to UDP yet,
|
||||
* however alot of p2p apps pretty much demand it.
|
||||
* The skeletal frame is here, just needs to be finished.
|
||||
*
|
||||
* @author sponge
|
||||
* @deprecated incomplete, unused
|
||||
*/
|
||||
@Deprecated
|
||||
public class UDPIOthread implements I2PSessionListener, Runnable {
|
||||
|
||||
private final NamedDB info;
|
||||
private final Log _log;
|
||||
private final Socket socket;
|
||||
private DataInputStream in;
|
||||
private DataOutputStream out;
|
||||
private final I2PSession _session;
|
||||
// FIXME never set
|
||||
private Destination _peerDestination;
|
||||
private boolean up;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param info
|
||||
* @param _log
|
||||
* @param socket
|
||||
* @param _session
|
||||
*/
|
||||
UDPIOthread(NamedDB info, Log _log, Socket socket, I2PSession _session) {
|
||||
this.info = info;
|
||||
this._log = _log;
|
||||
this.socket = socket;
|
||||
this._session = _session;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
byte data[] = new byte[1024];
|
||||
up = true;
|
||||
try {
|
||||
in = new DataInputStream(socket.getInputStream());
|
||||
out = new DataOutputStream(socket.getOutputStream());
|
||||
while (up) {
|
||||
int c = in.read(data);
|
||||
// Note: could do a loopback test here with a wrapper.
|
||||
boolean ok = _session.sendMessage(_peerDestination, data, 0, c);
|
||||
|
||||
if (!ok) {
|
||||
up = false; // Is this the right thing to do??
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Error running", ioe);
|
||||
} catch (I2PSessionException ise) {
|
||||
_log.error("Error communicating", ise);
|
||||
// } catch(DataFormatException dfe) {
|
||||
// _log.error("Peer destination file is not valid", dfe);
|
||||
} finally {
|
||||
if (_session != null) {
|
||||
try {
|
||||
_session.destroySession();
|
||||
} catch (I2PSessionException ise) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param session
|
||||
* @param msgId
|
||||
* @param size
|
||||
*/
|
||||
public void messageAvailable(I2PSession session, int msgId, long size) {
|
||||
// _log.debug("Message available: id = " + msgId + " size = " + size);
|
||||
try {
|
||||
byte msg[] = session.receiveMessage(msgId);
|
||||
if (msg != null) {
|
||||
out.write(msg);
|
||||
out.flush();
|
||||
}
|
||||
} catch (I2PSessionException ise) {
|
||||
up = false;
|
||||
} catch (IOException ioe) {
|
||||
up = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Great, can these be used to kill ourselves.
|
||||
/** required by {@link I2PSessionListener I2PSessionListener} to notify of disconnect */
|
||||
public void disconnected(I2PSession session) {
|
||||
_log.debug("Disconnected");
|
||||
// up = false;
|
||||
}
|
||||
|
||||
/** required by {@link I2PSessionListener I2PSessionListener} to notify of error */
|
||||
public void errorOccurred(I2PSession session, String message, Throwable error) {
|
||||
_log.debug("Error occurred: " + message, error);
|
||||
// up = false;
|
||||
}
|
||||
|
||||
/** required by {@link I2PSessionListener I2PSessionListener} to notify of abuse */
|
||||
public void reportAbuse(I2PSession session, int severity) {
|
||||
_log.debug("Abuse reported of severity " + severity);
|
||||
// up = false;
|
||||
}
|
||||
}
|
21
apps/BOB/src/net/i2p/BOB/license-WTFPL.txt
Normal file
21
apps/BOB/src/net/i2p/BOB/license-WTFPL.txt
Normal file
@ -0,0 +1,21 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) sponge
|
||||
Planet Earth
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
See...
|
||||
|
||||
http://sam.zoy.org/wtfpl/
|
||||
and
|
||||
http://en.wikipedia.org/wiki/WTFPL
|
||||
|
||||
...for any additional details and license questions.
|
5
apps/BOB/src/net/i2p/BOB/package.html
Normal file
5
apps/BOB/src/net/i2p/BOB/package.html
Normal file
@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>BOB, the Basic Open Bridge, allows TCP applications to talk over I2P - DEPRECATED - Please port applications to SAMv3.</p>
|
||||
</body>
|
||||
</html>
|
@ -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="," />
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -32,17 +32,14 @@ import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.app.ClientAppManager;
|
||||
import net.i2p.client.naming.HostTxtEntry;
|
||||
import net.i2p.client.naming.NamingService;
|
||||
import net.i2p.client.naming.SingleFileNamingService;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
import net.i2p.util.PortMapper;
|
||||
import net.i2p.util.SecureDirectory;
|
||||
import net.i2p.util.SystemVersion;
|
||||
import net.i2p.util.Translate;
|
||||
|
||||
/**
|
||||
* Main class of addressbook. Performs updates, and runs the main loop.
|
||||
@ -182,7 +179,6 @@ class Daemon {
|
||||
long start = DEBUG ? System.currentTimeMillis() : 0;
|
||||
int old = 0, nnew = 0, invalid = 0, conflict = 0, total = 0;
|
||||
int deleted = 0;
|
||||
String newname = null;
|
||||
while(iter.hasNext()) {
|
||||
Map.Entry<String, HostTxtEntry> entry = iter.next();
|
||||
total++;
|
||||
@ -281,8 +277,6 @@ class Daemon {
|
||||
if (log != null && !success)
|
||||
log.append("Add to published address book " + publishedNS.getName() + " failed for " + key);
|
||||
}
|
||||
if (nnew == 0)
|
||||
newname = key;
|
||||
nnew++;
|
||||
continue;
|
||||
} else {
|
||||
@ -506,8 +500,6 @@ class Daemon {
|
||||
// keep track for later dup check
|
||||
knownNames.add(key);
|
||||
}
|
||||
if (nnew == 0)
|
||||
newname = key;
|
||||
nnew++;
|
||||
} else if (key == null) {
|
||||
// 'remove' actions
|
||||
@ -677,24 +669,6 @@ class Daemon {
|
||||
invalid + " invalid, " +
|
||||
conflict + " conflicts");
|
||||
}
|
||||
if (nnew > 0) {
|
||||
ClientAppManager cmgr = I2PAppContext.getGlobalContext().clientAppManager();
|
||||
if (cmgr != null) {
|
||||
int nc = cmgr.getBubbleCount(PortMapper.SVC_SUSIDNS) + nnew;
|
||||
String msg = ngettext("{0} new host", "{0} new hosts", nc);
|
||||
if (nc == 1)
|
||||
msg += ": " + newname;
|
||||
cmgr.setBubble(PortMapper.SVC_SUSIDNS, nc, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* translate (ngettext) from the routerconsole bundle
|
||||
* @since 0.9.66
|
||||
*/
|
||||
private static String ngettext(String s, String p, int n) {
|
||||
return Translate.getString(n, s, p, I2PAppContext.getGlobalContext(), "net.i2p.router.web.messages");
|
||||
}
|
||||
|
||||
/** @since 0.9.26 */
|
||||
@ -723,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(", ");
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
@ -797,7 +793,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
||||
if (d != null)
|
||||
return d;
|
||||
// Base32 failed?
|
||||
if (hostname.length() >= BASE32_HASH_LENGTH + 8 && hostname.toLowerCase(Locale.US).endsWith(".b32.i2p"))
|
||||
if (hostname.length() == BASE32_HASH_LENGTH + 8 && hostname.toLowerCase(Locale.US).endsWith(".b32.i2p"))
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -848,7 +844,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
||||
*/
|
||||
private List<Destination> lookupAll2(String hostname, Properties lookupOptions, List<Properties> storedOptions) {
|
||||
// only use cache for b32
|
||||
if (hostname.length() >= BASE32_HASH_LENGTH + 8 && hostname.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
||||
if (hostname.length() == BASE32_HASH_LENGTH + 8 && hostname.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
||||
Destination d = super.lookup(hostname, null, null);
|
||||
if (d != null) {
|
||||
if (storedOptions != null)
|
||||
@ -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);
|
||||
|
@ -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>
|
@ -330,21 +330,8 @@ public class BSkipSpan<K extends Comparable<? super K>, V> extends SkipSpan<K, V
|
||||
break;
|
||||
}
|
||||
// System.out.println("i=" + i + ", Page " + curPage + ", offset " + pageCounter[0] + " ksz " + ksz + " vsz " + vsz);
|
||||
|
||||
try {
|
||||
this.keys[i] = this.keySer.construct(k);
|
||||
this.vals[i] = this.valSer.construct(v);
|
||||
} catch (Exception e) {
|
||||
// It's important to catch unchecked exceptions here,
|
||||
// so we can repair corruption below.
|
||||
// Ideally, the value deserializers should not throw
|
||||
// unchecked exceptions, and always return null, but
|
||||
// Destination can throw some IllegalArgumentExceptions.
|
||||
if (this.keys[i] != null)
|
||||
bf.log.error("Error loading key " + this.keys[i], e);
|
||||
else
|
||||
bf.log.error("Error loading entry " + i, e);
|
||||
}
|
||||
this.keys[i] = this.keySer.construct(k);
|
||||
this.vals[i] = this.valSer.construct(v);
|
||||
// Drop bad entry without throwing exception
|
||||
if (this.keys[i] == null || this.vals[i] == null) {
|
||||
bf.log.error("Null deserialized data in entry " + i + " page " + curPage +
|
||||
|
@ -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.
|
||||
|
@ -10,7 +10,6 @@
|
||||
<property name="javac.version" value="1.8" />
|
||||
<property name="javac.release" value="8" />
|
||||
<property name="require.gettext" value="true" />
|
||||
<property name="manifest.classpath.name" value="Class-Path" />
|
||||
|
||||
<condition property="no.bundle">
|
||||
<isfalse value="${require.gettext}" />
|
||||
@ -64,24 +63,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" >
|
||||
@ -94,7 +86,6 @@
|
||||
<jar basedir="${build}" excludes="messages-src/**" destfile="${dist}/${jar}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="net.i2p.desktopgui.Main"/>
|
||||
<attribute name="${manifest.classpath.name}" value="i2p.jar router.jar" />
|
||||
<attribute name="Implementation-Version" value="${full.version}" />
|
||||
<attribute name="Built-By" value="${build.built-by}" />
|
||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||
@ -115,7 +106,7 @@
|
||||
<not>
|
||||
<isset property="jar.uptodate" />
|
||||
</not>
|
||||
<isset property="git.available" />
|
||||
<isset property="mtn.available" />
|
||||
</and>
|
||||
</condition>
|
||||
</target>
|
||||
|
@ -138,12 +138,7 @@ do
|
||||
RC=1
|
||||
break
|
||||
fi
|
||||
# fixup Enumeration code for generics
|
||||
sed -e 's/Enumeration/Enumeration<String>/g' \
|
||||
-e 's/Object nextElement/String nextElement/g' \
|
||||
-e 's/return key/return (String) key/g' \
|
||||
$TDX/messages_$LG.java > $TDY/messages_$LG.java
|
||||
rm -f $TDX/messages_$LG.java
|
||||
mv $TDX/messages_$LG.java $TDY
|
||||
rm -rf $TD
|
||||
fi
|
||||
fi
|
||||
|
@ -10,9 +10,9 @@ 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: 2022-02-09 19:23+0000\n"
|
||||
"Last-Translator: zzzi2p\n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2017-09-20 20:31+0000\n"
|
||||
"Last-Translator: Vitaly Zdorovenko <stenliterziev@gmail.com>\n"
|
||||
"Language-Team: Bulgarian (http://www.transifex.com/otf/I2P/language/bg/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -27,81 +27,69 @@ msgstr "Стартиране на 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 е стартиран!"
|
||||
|
||||
#: 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:249
|
||||
#: 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:270
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
|
||||
msgid "Configure I2P System Tray"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
|
||||
msgid "Enable notifications"
|
||||
msgstr ""
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
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: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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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 "Рестартирайте Незабавно"
|
||||
|
||||
#: 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 ""
|
||||
|
||||
#: 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 ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "Изключване в {0}"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr ""
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
|
||||
msgid "Network"
|
||||
msgstr "Мрежа"
|
||||
msgstr ""
|
||||
|
||||
#. 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 ""
|
||||
|
@ -8,10 +8,10 @@ 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: duck <duck@mail.i2p>\n"
|
||||
"Language-Team: Catalan (http://app.transifex.com/otf/I2P/language/ca/)\n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
|
||||
"Last-Translator: zzzi2p\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/otf/I2P/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@ -19,84 +19,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 "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 s'està iniciant."
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
msgid "Starting"
|
||||
msgstr "Iniciant"
|
||||
|
||||
#: 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 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 ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
|
||||
msgid "Disable system tray"
|
||||
#: 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 "Reiniciar 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 "Aturar 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 ""
|
||||
|
||||
#: 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 ""
|
||||
|
||||
#: 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 ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "Apagament 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 "Xarxa"
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#: 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 ""
|
||||
|
@ -4,15 +4,14 @@
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# slrslr, 2022
|
||||
# slrslr, 2021
|
||||
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: slrslr, 2022\n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2021-07-08 09:41+0000\n"
|
||||
"Last-Translator: slrslr\n"
|
||||
"Language-Team: Czech (http://www.transifex.com/otf/I2P/language/cs/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -27,81 +26,69 @@ msgstr "Spustit 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 startuje!"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
msgid "Starting"
|
||||
msgstr "Startuji"
|
||||
|
||||
#: 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 "Spouštím I2P Browser"
|
||||
|
||||
#: 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 "Nastavit I2P Systémovou Lištu"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
|
||||
msgid "Enable notifications"
|
||||
msgstr "Zapnout upozornění"
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
msgstr "Zakázat"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
|
||||
msgid "Disable notifications"
|
||||
msgstr "Vypnout upozornění"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
|
||||
msgid "Disable system tray"
|
||||
msgstr "Vypnout ikonu systémové lišty"
|
||||
|
||||
#: 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 "Restart 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 "Zastavit 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 "Restartovat I2P Hned"
|
||||
|
||||
#: 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 "Zastavit I2P Hned"
|
||||
|
||||
#: 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 "Zrušit I2P Zastavení"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "Zastavení za {0}"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "Vypínání"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
|
||||
msgid "Network"
|
||||
msgstr "Síť"
|
||||
|
||||
#. 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: Pravé-kliknutí pro menu"
|
||||
|
@ -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ü"
|
||||
|
@ -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: 2021-08-11 15:33+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,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 ""
|
||||
|
||||
#: 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 ""
|
||||
|
||||
#: 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:54
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:206
|
||||
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:75
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:227
|
||||
msgid "Configure I2P System Tray"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
|
||||
msgid "Disable system tray"
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
|
||||
msgid "Disable"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:92
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
|
||||
msgid "Restart I2P"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:109
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:261
|
||||
msgid "Stop I2P"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:125
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
|
||||
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:142
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:294
|
||||
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:156
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:308
|
||||
msgid "Cancel I2P Shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:362
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:364
|
||||
msgid "Shutdown imminent"
|
||||
msgstr ""
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:369
|
||||
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 ""
|
||||
|
||||
#: 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 ""
|
||||
|
@ -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ú"
|
||||
|
@ -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ú"
|
||||
|
@ -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 d’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 "Configurer la zone de notification d’I2P"
|
||||
|
||||
#: 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 d’I2P"
|
||||
|
||||
#: 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"
|
||||
|
@ -1,102 +0,0 @@
|
||||
# I2P
|
||||
# Copyright (C) 2009 The I2P Project
|
||||
# This file is distributed under the same license as the desktopgui package.
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
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: duck <duck@mail.i2p>\n"
|
||||
"Language-Team: Chinese (Gan) (http://app.transifex.com/otf/I2P/language/gan/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: gan\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
|
||||
msgid "Start I2P"
|
||||
msgstr "啟動I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
msgid "I2P is starting!"
|
||||
msgstr " I2P 正在启动!"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
msgid "Starting"
|
||||
msgstr "開始"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
|
||||
msgid "Launch I2P Browser"
|
||||
msgstr "启动 I2P 浏览器"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
|
||||
msgid "Configure I2P System Tray"
|
||||
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:104
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
|
||||
msgid "Restart I2P"
|
||||
msgstr "重啟I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
|
||||
msgid "Stop I2P"
|
||||
msgstr "停止I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
|
||||
msgid "Restart I2P Immediately"
|
||||
msgstr "強制重啟I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
|
||||
msgid "Stop I2P Immediately"
|
||||
msgstr "強制終止I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
|
||||
msgid "Cancel I2P Shutdown"
|
||||
msgstr "取消停止I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "關閉於 {0}"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "強制關閉"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
|
||||
msgid "Network"
|
||||
msgstr "网络"
|
||||
|
||||
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:75
|
||||
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 "禁用通知"
|
@ -1,103 +0,0 @@
|
||||
# I2P
|
||||
# Copyright (C) 2009 The I2P Project
|
||||
# This file is distributed under the same license as the desktopgui package.
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# absolutep, 2025
|
||||
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: absolutep, 2025\n"
|
||||
"Language-Team: Hindi (http://app.transifex.com/otf/I2P/language/hi/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: hi\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
|
||||
msgid "Start I2P"
|
||||
msgstr "I2P प्रारंभ करें"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
msgid "I2P is starting!"
|
||||
msgstr "I2P प्रारंभ हो रहा है"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
msgid "Starting"
|
||||
msgstr "प्रारंभ हो रहा है"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
|
||||
msgid "Launch I2P Browser"
|
||||
msgstr "I2P ब्राउज़र को आरंभ करें"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
|
||||
msgid "Configure I2P System Tray"
|
||||
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:104
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
|
||||
msgid "Restart I2P"
|
||||
msgstr "I2P को पुनः सञ्चालित करें"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
|
||||
msgid "Stop I2P"
|
||||
msgstr "I2P को निष्क्रिय करें"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
|
||||
msgid "Restart I2P Immediately"
|
||||
msgstr "I2P को तत्काल पुनः सञ्चालित करें"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
|
||||
msgid "Stop I2P Immediately"
|
||||
msgstr "I2P को तत्काल निष्क्रिय करें"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
|
||||
msgid "Cancel I2P Shutdown"
|
||||
msgstr "I2P निष्करण को निरस्त करें"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "{0} में निष्करण होगा"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "निष्करण शीघ्र होने वाला है"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
|
||||
msgid "Network"
|
||||
msgstr "नेटवर्क"
|
||||
|
||||
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:75
|
||||
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 "सूचनाओं को निष्क्रिय करें"
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -4,17 +4,16 @@
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# daingewuvzeevisiddfddd, 2022,2025
|
||||
# タカハシ, 2013
|
||||
# タカハシ <indexial@outlook.jp>, 2013
|
||||
# Masayuki Hatta <mhatta@mhatta.org>, 2018
|
||||
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: daingewuvzeevisiddfddd, 2022,2025\n"
|
||||
"Language-Team: Japanese (http://app.transifex.com/otf/I2P/language/ja/)\n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2018-08-17 22:08+0000\n"
|
||||
"Last-Translator: Masayuki Hatta <mhatta@mhatta.org>\n"
|
||||
"Language-Team: Japanese (http://www.transifex.com/otf/I2P/language/ja/)\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 "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 "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 "間も無くシャットダウン"
|
||||
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 "通知を無効化"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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: Правый щелчок для вызова меню"
|
||||
|
@ -1,106 +0,0 @@
|
||||
# I2P
|
||||
# Copyright (C) 2009 The I2P Project
|
||||
# This file is distributed under the same license as the desktopgui package.
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# Žan Šadl-Ferš, 2021
|
||||
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: 2022-02-09 19:23+0000\n"
|
||||
"Last-Translator: zzzi2p\n"
|
||||
"Language-Team: Slovenian (http://www.transifex.com/otf/I2P/language/sl/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: sl\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
|
||||
msgid "Start I2P"
|
||||
msgstr "Zaženi 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 se zaganja!"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
msgid "Starting"
|
||||
msgstr "Zaganja"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
|
||||
msgid "Launch I2P Browser"
|
||||
msgstr "Zaženi I2P brskalnik"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
|
||||
msgid "Configure I2P System Tray"
|
||||
msgstr "Konfiguriraj I2P opravilno vrstico"
|
||||
|
||||
#: 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:131
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
|
||||
msgid "Restart I2P"
|
||||
msgstr "Ponovno zaženi I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
|
||||
msgid "Stop I2P"
|
||||
msgstr "Ustavi I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
|
||||
msgid "Restart I2P Immediately"
|
||||
msgstr "Nemudoma ponovno zaženi I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Stop I2P Immediately"
|
||||
msgstr "Nemudoma ustavi I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
|
||||
msgid "Cancel I2P Shutdown"
|
||||
msgstr "Prekliči zaustavitev od I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "Zaustavi v {0}"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "Zaustavitev je neizbežna"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
|
||||
msgid "Network"
|
||||
msgstr "Omrežje"
|
||||
|
||||
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:73
|
||||
msgid "I2P: Right-click for menu"
|
||||
msgstr "I2P: Pritisnite na desno tipko miške za meni"
|
@ -4,16 +4,15 @@
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# Besnik Bleta <besnik@programeshqip.org>, 2022
|
||||
# Besnik Bleta <besnik@programeshqip.org>, 2016,2019
|
||||
# Besnik <besnik@programeshqip.org>, 2016,2019
|
||||
# Shpetim <shpetim@privacysolutions.no>, 2014
|
||||
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: 2022-02-10 10:34+0000\n"
|
||||
"Last-Translator: Besnik Bleta <besnik@programeshqip.org>\n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2019-01-10 14:28+0000\n"
|
||||
"Last-Translator: Besnik <besnik@programeshqip.org>\n"
|
||||
"Language-Team: Albanian (http://www.transifex.com/otf/I2P/language/sq/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -28,81 +27,69 @@ msgstr "Nise I2P-në"
|
||||
|
||||
#: 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 po niset!"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
msgid "Starting"
|
||||
msgstr "Po niset"
|
||||
|
||||
#: 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 "Nis Shfletuesin 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 "Formësoni Panel Sistemi I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
|
||||
msgid "Enable notifications"
|
||||
msgstr "Aktivizoni njoftimet"
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
msgstr "Çaktivizoje"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
|
||||
msgid "Disable notifications"
|
||||
msgstr "Çaktivizoni njoftimet"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
|
||||
msgid "Disable system tray"
|
||||
msgstr "Çaktivizo panel sistemi"
|
||||
|
||||
#: 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 "Rinise I2P-në"
|
||||
|
||||
#: 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 "Ndale I2P-në"
|
||||
|
||||
#: 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 "Rinise I2P-në Menjëherë"
|
||||
|
||||
#: 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 "Ndale I2P-në Menjëherë"
|
||||
|
||||
#: 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 "Anuloje Mbylljen e I2P-së"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "Mbylle për {0}"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "Mbyllje shumë shpejt"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
|
||||
msgid "Network"
|
||||
msgstr "Rrjet"
|
||||
|
||||
#. 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: Djathtasklikoni për menu"
|
||||
|
@ -4,100 +4,91 @@
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# Kaya Zeren <kayazeren@gmail.com>, 2013,2016,2022,2025
|
||||
# Kaya Zeren <kayazeren@gmail.com>, 2013,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: Kaya Zeren <kayazeren@gmail.com>, 2013,2016,2022,2025\n"
|
||||
"Language-Team: Turkish (Turkey) (http://app.transifex.com/otf/I2P/language/tr_TR/)\n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
|
||||
"Last-Translator: Kaya Zeren <kayazeren@gmail.com>\n"
|
||||
"Language-Team: Turkish (Turkey) (http://www.transifex.com/otf/I2P/language/tr_TR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: tr_TR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"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 "I2P başlasın"
|
||||
|
||||
#: 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 başlatılıyor!"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
msgid "Starting"
|
||||
msgstr "Başlatılıyor"
|
||||
|
||||
#: 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 tarayıcısını aç"
|
||||
msgstr "I2P Tarayıcısını Açın"
|
||||
|
||||
#: 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 "I2P sistem tepsisi ayarları"
|
||||
msgstr "I2P Sistem Tepsisi Ayarları"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
|
||||
msgid "Disable system tray"
|
||||
msgstr "Sistem tepsisini etkisizleştir"
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
msgstr "Devre Dışı"
|
||||
|
||||
#: 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 yeniden başlasın"
|
||||
msgstr "I2P Yeniden Başlasın"
|
||||
|
||||
#: 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 durdurulsun"
|
||||
msgstr "I2P Durdurulsun"
|
||||
|
||||
#: 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 hemen yeniden başlatılsın"
|
||||
msgstr "I2P Hemen Yeniden Başlatılsın"
|
||||
|
||||
#: 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 hemen durdurulsun"
|
||||
msgstr "I2P Hemen Durdurulsun"
|
||||
|
||||
#: 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 kapatmayı iptal et"
|
||||
msgstr "I2P Kapatmayı İptal Et"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "{0} içinde kapat"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "Kapatılmak üzere"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
|
||||
msgid "Network"
|
||||
msgstr "Ağ"
|
||||
|
||||
#. 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: Menüde sağ tık"
|
||||
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:310
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:347
|
||||
msgid "Enable notifications"
|
||||
msgstr "Bildirimleri etkinleştir"
|
||||
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:325
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:362
|
||||
msgid "Disable notifications"
|
||||
msgstr "Bildirimleri etkisizleştir"
|
||||
|
@ -5,15 +5,15 @@
|
||||
#
|
||||
# Translators:
|
||||
# ducki2p <ducki2p@gmail.com>, 2011
|
||||
# Scott Rhodes <starring169@gmail.com>, 2021-2022
|
||||
# Scott Rhodes <starring169@gmail.com>, 2021
|
||||
# walking <walking@i2pmail.org>, 2011
|
||||
# YFdyh000 <yfdyh000@gmail.com>, 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: 2022-02-16 16:05+0000\n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2021-03-07 07:58+0000\n"
|
||||
"Last-Translator: Scott Rhodes <starring169@gmail.com>\n"
|
||||
"Language-Team: Chinese (China) (http://www.transifex.com/otf/I2P/language/zh_CN/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -29,81 +29,69 @@ msgstr "启动 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 正在启动!"
|
||||
|
||||
#: 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:249
|
||||
#: 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:270
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
|
||||
msgid "Configure I2P System Tray"
|
||||
msgstr "配置 I2P 系统托盘"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
|
||||
msgid "Enable notifications"
|
||||
msgstr "启用通知"
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
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: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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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 关闭"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "{0} 后关闭"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "立即关闭"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
|
||||
#: 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:73
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:63
|
||||
msgid "I2P: Right-click for menu"
|
||||
msgstr "I2P:右击获得菜单"
|
||||
|
@ -9,9 +9,9 @@ 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: 黃彥儒 <r1235613@gmail.com>, 2017\n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2018-10-04 00:43+0000\n"
|
||||
"Last-Translator: erinm\n"
|
||||
"Language-Team: Chinese (Taiwan) (http://www.transifex.com/otf/I2P/language/zh_TW/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -26,81 +26,69 @@ msgstr "啟動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已啟動"
|
||||
|
||||
#: 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:249
|
||||
#: 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:270
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
|
||||
msgid "Configure I2P System Tray"
|
||||
msgstr "設定I2P系統文件夾"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
|
||||
msgid "Enable notifications"
|
||||
msgstr "启用通知"
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
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: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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "關閉於 {0}"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "強制關閉"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
|
||||
#: 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:73
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:63
|
||||
msgid "I2P: Right-click for menu"
|
||||
msgstr "I2P:右鍵開啟選單"
|
||||
|
@ -1,312 +0,0 @@
|
||||
package net.i2p.desktopgui;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.Toolkit;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* A simplified Main that does not require router.jar, for App Context only.
|
||||
* Invokes ExternalTrayManager only.
|
||||
* No state tracking, ClientAppManager doesn't care.
|
||||
*
|
||||
* @since 0.9.54
|
||||
*/
|
||||
public class ExternalMain implements ClientApp, NotificationService, MenuService {
|
||||
|
||||
private final I2PAppContext _appContext;
|
||||
private final ClientAppManager _mgr;
|
||||
private final Log log;
|
||||
private TrayManager _trayManager;
|
||||
|
||||
private static final String PROP_SWING = "desktopgui.swing";
|
||||
|
||||
public ExternalMain(I2PAppContext ctx, ClientAppManager mgr, String args[]) {
|
||||
_appContext = ctx;
|
||||
_mgr = mgr;
|
||||
log = _appContext.logManager().getLog(ExternalMain.class);
|
||||
}
|
||||
|
||||
public ExternalMain() {
|
||||
_appContext = I2PAppContext.getGlobalContext();
|
||||
_mgr = _appContext.clientAppManager();
|
||||
log = _appContext.logManager().getLog(ExternalMain.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// early check so we can bail out when started via CLI
|
||||
if (!SystemTray.isSupported()) {
|
||||
System.err.println("SystemTray not supported");
|
||||
return;
|
||||
}
|
||||
ExternalMain main = new ExternalMain();
|
||||
main.beginStartup(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the tray icon code (loads tray icon in the tray area).
|
||||
* @throws AWTException on startup error, including systray not supported
|
||||
*/
|
||||
private synchronized void startUp() throws Exception {
|
||||
boolean useSwingDefault = !(SystemVersion.isWindows() || SystemVersion.isMac());
|
||||
boolean useSwing = _appContext.getProperty(PROP_SWING, useSwingDefault);
|
||||
_trayManager = new ExternalTrayManager(_appContext, useSwing);
|
||||
_trayManager.startManager();
|
||||
if (_mgr != null)
|
||||
_mgr.register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method launching the application.
|
||||
*
|
||||
* @param args unused
|
||||
*/
|
||||
private void beginStartup(String[] args) {
|
||||
String headless = System.getProperty("java.awt.headless");
|
||||
boolean isHeadless = Boolean.parseBoolean(headless);
|
||||
if (isHeadless) {
|
||||
log.warn("Headless environment: not starting desktopgui!");
|
||||
return;
|
||||
}
|
||||
if (SystemVersion.isMac())
|
||||
setMacTrayIcon();
|
||||
launchForeverLoop();
|
||||
|
||||
// We'll be doing GUI work, so let's stay in the event dispatcher thread.
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
startUp();
|
||||
} catch(Exception e) {
|
||||
log.error("Failed while running desktopgui!", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unless we do this, when we start DesktopGUI we get a Java coffee cup
|
||||
* in the tray.
|
||||
*
|
||||
* Based on code from https://gist.github.com/bchapuis/1562406 , no apparent license.
|
||||
* See also https://stackoverflow.com/questions/6006173/how-do-you-change-the-dock-icon-of-a-java-program
|
||||
*
|
||||
* TODO, if we wanted to add our own menu, see
|
||||
* https://stackoverflow.com/questions/1319805/java-os-x-dock-menu
|
||||
*
|
||||
* TODO, if we want to make it bounce, see
|
||||
* https://stackoverflow.com/questions/15079783/how-to-make-my-app-icon-bounce-in-the-mac-dock
|
||||
*
|
||||
* TODO, if we want to handle Quit, see
|
||||
* https://nakkaya.com/2009/04/19/java-osx-integration/
|
||||
*
|
||||
* @since 0.9.33
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void setMacTrayIcon() {
|
||||
File f = new File(_appContext.getBaseDir(), "docs/themes/console/images/itoopie_sm.png");
|
||||
if (!f.exists())
|
||||
return;
|
||||
try {
|
||||
Class util = Class.forName("com.apple.eawt.Application");
|
||||
Method getApplication = util.getMethod("getApplication", new Class[0]);
|
||||
Object application = getApplication.invoke(util);
|
||||
Class params[] = new Class[1];
|
||||
params[0] = Image.class;
|
||||
Method setDockIconImage = util.getMethod("setDockIconImage", params);
|
||||
URL url = f.toURI().toURL();
|
||||
Image image = Toolkit.getDefaultToolkit().getImage(url);
|
||||
setDockIconImage.invoke(application, image);
|
||||
} catch (Exception e) {
|
||||
if (log.shouldWarn())
|
||||
log.warn("Can't set OSX Dock icon", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoids the app terminating because no Window is opened anymore.
|
||||
* More info: http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown
|
||||
*/
|
||||
private static void launchForeverLoop() {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
Object o = new Object();
|
||||
synchronized (o) {
|
||||
o.wait();
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
};
|
||||
Thread t = new Thread(r, "DesktopGUI spinner");
|
||||
t.setDaemon(false);
|
||||
t.start();
|
||||
}
|
||||
|
||||
/////// NotificationService methods
|
||||
|
||||
/**
|
||||
* Send a notification to the user.
|
||||
*
|
||||
* @param source unsupported
|
||||
* @param category unsupported
|
||||
* @param priority unsupported
|
||||
* @param title for the popup, translated
|
||||
* @param message translated
|
||||
* @param path unsupported
|
||||
* @return 0, or -1 on failure
|
||||
*/
|
||||
public int notify(String source, String category, int priority, String title, String message, String path) {
|
||||
TrayManager tm = _trayManager;
|
||||
if (tm == null)
|
||||
return -1;
|
||||
return tm.displayMessage(priority, title, message, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a notification if possible.
|
||||
* Unsupported.
|
||||
*
|
||||
* @return false always
|
||||
*/
|
||||
public boolean cancel(int id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the text of a notification if possible.
|
||||
* Unsupported.
|
||||
*
|
||||
* @return false always
|
||||
*/
|
||||
public boolean update(int id, String title, String message, String path) {
|
||||
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() {
|
||||
beginStartup(null);
|
||||
}
|
||||
|
||||
public synchronized void shutdown(String[] args) {
|
||||
if (_trayManager != null)
|
||||
_trayManager.stopManager();
|
||||
}
|
||||
|
||||
public ClientAppState getState() {
|
||||
return ClientAppState.INITIALIZED;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "desktopgui";
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Desktop GUI";
|
||||
}
|
||||
|
||||
/////// end ClientApp methods
|
||||
}
|
@ -22,8 +22,8 @@ import net.i2p.desktopgui.router.RouterManager;
|
||||
*/
|
||||
class ExternalTrayManager extends TrayManager {
|
||||
|
||||
public ExternalTrayManager(I2PAppContext ctx, boolean useSwing) {
|
||||
super(ctx, useSwing);
|
||||
public ExternalTrayManager(I2PAppContext ctx, Main main, boolean useSwing) {
|
||||
super(ctx, main, useSwing);
|
||||
}
|
||||
|
||||
public PopupMenu getMainMenu() {
|
||||
@ -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() {}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.i2p.desktopgui;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Desktop.Action;
|
||||
import java.awt.MenuItem;
|
||||
@ -30,7 +29,6 @@ class InternalTrayManager extends TrayManager {
|
||||
|
||||
private final RouterContext _context;
|
||||
private final Log log;
|
||||
private final Main _main;
|
||||
private MenuItem _statusItem, _browserItem, _configItem, _restartItem, _stopItem,
|
||||
_restartHardItem, _stopHardItem, _cancelItem;
|
||||
private JMenuItem _jstatusItem, _jbrowserItem, _jconfigItem, _jrestartItem, _jstopItem,
|
||||
@ -41,20 +39,11 @@ class InternalTrayManager extends TrayManager {
|
||||
private static final String CONSOLE_BUNDLE_NAME = "net.i2p.router.web.messages";
|
||||
|
||||
public InternalTrayManager(RouterContext ctx, Main main, boolean useSwing) {
|
||||
super(ctx, useSwing);
|
||||
super(ctx, main, useSwing);
|
||||
_context = ctx;
|
||||
_main = main;
|
||||
log = ctx.logManager().getLog(InternalTrayManager.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.53
|
||||
*/
|
||||
public void startManager() throws AWTException {
|
||||
super.startManager();
|
||||
displayMessage(Log.INFO, _t("Starting"), _t("I2P is starting!"), null);
|
||||
}
|
||||
|
||||
public synchronized PopupMenu getMainMenu() {
|
||||
PopupMenu popup = new PopupMenu();
|
||||
|
||||
@ -84,8 +73,7 @@ class InternalTrayManager extends TrayManager {
|
||||
}
|
||||
|
||||
PopupMenu desktopguiConfigurationLauncher = new PopupMenu(_t("Configure I2P System Tray"));
|
||||
|
||||
MenuItem configSubmenu = new MenuItem(_t("Disable system tray"));
|
||||
MenuItem configSubmenu = new MenuItem(_t("Disable"));
|
||||
configSubmenu.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
@ -185,9 +173,6 @@ class InternalTrayManager extends TrayManager {
|
||||
popup.add(browserLauncher);
|
||||
popup.addSeparator();
|
||||
}
|
||||
initializeNotificationItems();
|
||||
desktopguiConfigurationLauncher.add(_notificationItem2);
|
||||
desktopguiConfigurationLauncher.add(_notificationItem1);
|
||||
desktopguiConfigurationLauncher.add(configSubmenu);
|
||||
popup.add(desktopguiConfigurationLauncher);
|
||||
popup.addSeparator();
|
||||
@ -240,8 +225,7 @@ class InternalTrayManager extends TrayManager {
|
||||
}
|
||||
|
||||
JMenu desktopguiConfigurationLauncher = new JMenu(_t("Configure I2P System Tray"));
|
||||
|
||||
JMenuItem configSubmenu = new JMenuItem(_t("Disable system tray"));
|
||||
JMenuItem configSubmenu = new JMenuItem(_t("Disable"));
|
||||
configSubmenu.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
@ -341,9 +325,6 @@ class InternalTrayManager extends TrayManager {
|
||||
popup.add(browserLauncher);
|
||||
popup.addSeparator();
|
||||
}
|
||||
initializeJNotificationItems();
|
||||
desktopguiConfigurationLauncher.add(_jnotificationItem2);
|
||||
desktopguiConfigurationLauncher.add(_jnotificationItem1);
|
||||
desktopguiConfigurationLauncher.add(configSubmenu);
|
||||
popup.add(desktopguiConfigurationLauncher);
|
||||
popup.addSeparator();
|
||||
@ -409,10 +390,6 @@ class InternalTrayManager extends TrayManager {
|
||||
_stopHardItem.setEnabled(!imminent);
|
||||
if (_cancelItem != null)
|
||||
_cancelItem.setEnabled(x && !imminent);
|
||||
if (_notificationItem1 != null)
|
||||
_notificationItem1.setEnabled(_showNotifications);
|
||||
if (_notificationItem2 != null)
|
||||
_notificationItem2.setEnabled(!_showNotifications);
|
||||
|
||||
if (_jstatusItem != null)
|
||||
_jstatusItem.setText(status);
|
||||
@ -430,10 +407,6 @@ class InternalTrayManager extends TrayManager {
|
||||
_jstopHardItem.setVisible(!imminent);
|
||||
if (_jcancelItem != null)
|
||||
_jcancelItem.setVisible(x && !imminent);
|
||||
if (_jnotificationItem1 != null)
|
||||
_jnotificationItem1.setVisible(_showNotifications);
|
||||
if (_jnotificationItem2 != null)
|
||||
_jnotificationItem2.setVisible(!_showNotifications);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -442,23 +415,16 @@ class InternalTrayManager extends TrayManager {
|
||||
private void configureDesktopgui(boolean enable) {
|
||||
String property = Main.PROP_ENABLE;
|
||||
String value = Boolean.toString(enable);
|
||||
if (!_context.router().saveConfig(property, value))
|
||||
log.error("Error saving config");
|
||||
if (!enable) {
|
||||
// TODO popup that explains how to re-enable in console
|
||||
_main.shutdown(null);
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
||||
/**
|
||||
* @since 0.9.53
|
||||
*/
|
||||
@Override
|
||||
protected void configureNotifications(boolean enable) {
|
||||
_showNotifications = enable;
|
||||
String value = Boolean.toString(enable);
|
||||
if (!_context.router().saveConfig(PROP_NOTIFICATIONS, value))
|
||||
log.error("Error saving config");
|
||||
_context.router().saveConfig(property, value);
|
||||
if (!enable) {
|
||||
// TODO popup that explains how to re-enable in console
|
||||
_main.shutdown(null);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("Error saving config", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,6 @@ package net.i2p.desktopgui;
|
||||
*/
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.Toolkit;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
@ -17,10 +16,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;
|
||||
import net.i2p.router.app.RouterApp;
|
||||
@ -32,7 +27,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 {
|
||||
|
||||
// non-null
|
||||
private final I2PAppContext _appContext;
|
||||
@ -60,7 +55,7 @@ public class Main implements RouterApp, NotificationService, MenuService {
|
||||
*/
|
||||
public Main() {
|
||||
_appContext = I2PAppContext.getGlobalContext();
|
||||
if (_appContext.isRouterContext())
|
||||
if (_appContext instanceof RouterContext)
|
||||
_context = (RouterContext) _appContext;
|
||||
else
|
||||
_context = null;
|
||||
@ -80,7 +75,7 @@ public class Main implements RouterApp, NotificationService, MenuService {
|
||||
if (_context != null)
|
||||
trayManager = new InternalTrayManager(_context, this, useSwing);
|
||||
else
|
||||
trayManager = new ExternalTrayManager(_appContext, useSwing);
|
||||
trayManager = new ExternalTrayManager(_appContext, this, useSwing);
|
||||
trayManager.startManager();
|
||||
_trayManager = trayManager;
|
||||
changeState(RUNNING);
|
||||
@ -100,11 +95,6 @@ public class Main implements RouterApp, NotificationService, MenuService {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// early check so we can bail out when started via CLI
|
||||
if (!SystemTray.isSupported()) {
|
||||
System.err.println("SystemTray not supported");
|
||||
return;
|
||||
}
|
||||
Main main = new Main();
|
||||
main.beginStartup(args);
|
||||
}
|
||||
@ -208,129 +198,6 @@ public class Main implements RouterApp, NotificationService, MenuService {
|
||||
t.start();
|
||||
}
|
||||
|
||||
/////// NotificationService methods
|
||||
|
||||
/**
|
||||
* Send a notification to the user.
|
||||
*
|
||||
* @param source unsupported
|
||||
* @param category unsupported
|
||||
* @param priority unsupported
|
||||
* @param title for the popup, translated
|
||||
* @param message translated
|
||||
* @param path unsupported
|
||||
* @return 0, or -1 on failure
|
||||
*/
|
||||
public int notify(String source, String category, int priority, String title, String message, String path) {
|
||||
TrayManager tm = _trayManager;
|
||||
if (tm == null)
|
||||
return -1;
|
||||
return tm.displayMessage(priority, title, message, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a notification if possible.
|
||||
* Unsupported.
|
||||
*
|
||||
* @return false always
|
||||
*/
|
||||
public boolean cancel(int id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the text of a notification if possible.
|
||||
* Unsupported.
|
||||
*
|
||||
* @return false always
|
||||
*/
|
||||
public boolean update(int id, String title, String message, String path) {
|
||||
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 */
|
||||
|
@ -4,38 +4,25 @@ 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;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
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;
|
||||
import javax.swing.event.MenuKeyListener;
|
||||
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;
|
||||
import net.i2p.util.SystemVersion;
|
||||
|
||||
/**
|
||||
@ -44,32 +31,25 @@ import net.i2p.util.SystemVersion;
|
||||
abstract class TrayManager {
|
||||
|
||||
protected final I2PAppContext _appContext;
|
||||
protected final Main _main;
|
||||
protected final boolean _useSwing;
|
||||
///The tray area, or null if unsupported
|
||||
protected SystemTray tray;
|
||||
///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";
|
||||
private static final String WIN_ICON_LIGHT = "itoopie_white_24.png";
|
||||
private static final String WIN_ICON_DARK = "itoopie_black_24.png";
|
||||
private static final String WIN_ICON = "itoopie_white_24.png";
|
||||
private static final String LIN_ICON = "logo.png";
|
||||
protected static final String PROP_NOTIFICATIONS = "desktopgui.showNotifications";
|
||||
|
||||
/**
|
||||
* Instantiate tray manager.
|
||||
*/
|
||||
protected TrayManager(I2PAppContext ctx, boolean useSwing) {
|
||||
protected TrayManager(I2PAppContext ctx, Main main, boolean useSwing) {
|
||||
_appContext = ctx;
|
||||
_main = main;
|
||||
_useSwing = useSwing;
|
||||
_menus = new ArrayList<MenuInternal>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,7 +58,6 @@ abstract class TrayManager {
|
||||
public synchronized void startManager() throws AWTException {
|
||||
if (!SystemTray.isSupported())
|
||||
throw new AWTException("SystemTray not supported");
|
||||
_showNotifications = _appContext.getBooleanPropertyDefaultTrue(PROP_NOTIFICATIONS);
|
||||
tray = SystemTray.getSystemTray();
|
||||
// Windows typically has tooltips; Linux (at least Ubuntu) doesn't
|
||||
String tooltip = SystemVersion.isWindows() ? _t("I2P: Right-click for menu") : null;
|
||||
@ -118,7 +97,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);
|
||||
@ -213,20 +191,12 @@ abstract class TrayManager {
|
||||
*/
|
||||
private Image getTrayImage() throws AWTException {
|
||||
String img;
|
||||
if (SystemVersion.isWindows()) {
|
||||
// too hard to get the theme out of the registry,
|
||||
// use our console theme as a best guess
|
||||
// so we have a contrasting icon
|
||||
String theme = _appContext.getProperty("routerconsole.theme", "light");
|
||||
if (theme.equals("dark"))
|
||||
img = WIN_ICON_LIGHT;
|
||||
else
|
||||
img = WIN_ICON_DARK;
|
||||
} else if (SystemVersion.isMac()) {
|
||||
if (SystemVersion.isWindows())
|
||||
img = WIN_ICON;
|
||||
else if (SystemVersion.isMac())
|
||||
img = MAC_ICON;
|
||||
} else {
|
||||
else
|
||||
img = LIN_ICON;
|
||||
}
|
||||
URL url = getClass().getResource(PNG_DIR + img);
|
||||
if (url == null)
|
||||
throw new AWTException("cannot load tray image " + img);
|
||||
@ -234,316 +204,6 @@ abstract class TrayManager {
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a notification to the user.
|
||||
*
|
||||
* @param title for the popup, translated
|
||||
* @param message translated
|
||||
* @param path unsupported
|
||||
* @return 0, or -1 on failure
|
||||
*/
|
||||
public int displayMessage(int priority, String title, String message, String path) {
|
||||
if (!_showNotifications)
|
||||
return -1;
|
||||
final TrayIcon ti = trayIcon;
|
||||
if (ti == null)
|
||||
return -1;
|
||||
TrayIcon.MessageType type;
|
||||
if (priority <= Log.DEBUG)
|
||||
type = TrayIcon.MessageType.NONE;
|
||||
else if (priority <= Log.INFO)
|
||||
type = TrayIcon.MessageType.INFO;
|
||||
else if (priority <= Log.WARN)
|
||||
type = TrayIcon.MessageType.WARNING;
|
||||
else
|
||||
type = TrayIcon.MessageType.ERROR;
|
||||
ti.displayMessage(title, message, type);
|
||||
/*
|
||||
* There's apparently no way to bind a particular message to an action
|
||||
that comes back. We can't keep a queue because we don't get
|
||||
an action back when the message is removed via timeout or user x-out.
|
||||
On OSX, new messages dismiss previous ones.
|
||||
On LXDE (and Gnome?), new messages go under previous ones. Timeout is only 10 seconds.
|
||||
Message timeout is platform-dependent.
|
||||
So the order of events is unknowable.
|
||||
This only works if there is only one message ever.
|
||||
|
||||
if (path != null && path.length() > 0) {
|
||||
if (path.charAt(0) == '/');
|
||||
path = path.substring(1);
|
||||
final String url = _appContext.portMapper().getConsoleURL() + path;
|
||||
ti.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
ti.removeActionListener(this);
|
||||
new SwingWorker<Object, Object>() {
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
System.out.println("DIB " + arg0);
|
||||
UrlLauncher launcher = new UrlLauncher(_appContext, null, null);
|
||||
try {
|
||||
launcher.openUrl(url);
|
||||
System.out.println("DIB success " + url);
|
||||
} catch (IOException e1) {
|
||||
System.out.println("DIB fail " + url);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
System.out.println("done " + arg0);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
@ -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')
|
||||
}
|
||||
|
||||
|
@ -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" >
|
||||
|
@ -162,7 +162,6 @@ public class Dispatcher implements RequestHandler, NotificationHandler {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public JSONRPC2Response dispatch(final JSONRPC2Request request, final MessageContext requestCtx) {
|
||||
|
||||
return process(request, requestCtx);
|
||||
@ -210,7 +209,6 @@ public class Dispatcher implements RequestHandler, NotificationHandler {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public void dispatch(final JSONRPC2Notification notification, final MessageContext notificationCtx) {
|
||||
|
||||
process(notification, notificationCtx);
|
||||
|
@ -12,7 +12,7 @@ import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.apache.http.conn.util.InetAddressUtils;
|
||||
import org.apache.http.conn.util.InetAddressUtils;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
|
@ -156,11 +156,11 @@ public class JSONRPC2Servlet extends HttpServlet {
|
||||
} else {
|
||||
out.println("<p>Current API password:<input name=\"password\" type=\"password\">");
|
||||
}
|
||||
out.println("<p>New API password (twice): <input name=\"password2\" type=\"password\"> " +
|
||||
"<input name=\"password3\" type=\"password\"> " +
|
||||
out.println("<p>New API password (twice):<input name=\"password2\" type=\"password\">" +
|
||||
"<input name=\"password3\" type=\"password\">" +
|
||||
"<input name=\"save\" type=\"submit\" value=\"Change API Password\">" +
|
||||
"<p>If you forget the API password, <a href=\"/configwebapps\">stop jsonrpc</a>, delete the file <tt>" + _conf.getConfFile() +
|
||||
"</tt>, and <a href=\"/configwebapps\">restart jsonrpc</a>.");
|
||||
"<p>If you forget the API password, stop i2pcontrol, delete the file <tt>" + _conf.getConfFile() +
|
||||
"</tt>, and restart i2pcontrol.");
|
||||
out.println("</form>");
|
||||
} else {
|
||||
out.println("<p><a href=\"password\">Change API Password</a>");
|
||||
|
@ -96,7 +96,7 @@ public class RouterInfoHandler implements RequestHandler {
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.status")) {
|
||||
outParams.put("i2p.router.status", _context.throttle().getLocalizedTunnelStatus());
|
||||
outParams.put("i2p.router.status", _context.throttle().getTunnelStatus());
|
||||
}
|
||||
|
||||
if (inParams.containsKey("i2p.router.net.status")) {
|
||||
@ -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;
|
||||
@ -179,44 +179,25 @@ public class RouterInfoHandler implements RequestHandler {
|
||||
|
||||
int status = _context.commSystem().getStatus().getCode();
|
||||
switch (status) {
|
||||
|
||||
case CommSystemFacade.STATUS_OK:
|
||||
case CommSystemFacade.STATUS_IPV4_OK_IPV6_UNKNOWN:
|
||||
case CommSystemFacade.STATUS_IPV4_OK_IPV6_FIREWALLED:
|
||||
case CommSystemFacade.STATUS_IPV4_FIREWALLED_IPV6_OK:
|
||||
case CommSystemFacade.STATUS_IPV4_DISABLED_IPV6_OK:
|
||||
RouterAddress ra = _context.router().getRouterInfo().getTargetAddress("NTCP2");
|
||||
case CommSystemFacade.STATUS_OK:
|
||||
RouterAddress ra = _context.router().getRouterInfo().getTargetAddress("NTCP");
|
||||
if (ra == null || TransportUtil.isPubliclyRoutable(ra.getIP(), true))
|
||||
return NETWORK_STATUS.OK;
|
||||
return NETWORK_STATUS.ERROR_PRIVATE_TCP_ADDRESS;
|
||||
|
||||
case CommSystemFacade.STATUS_DIFFERENT:
|
||||
case CommSystemFacade.STATUS_IPV4_SNAT_IPV6_OK:
|
||||
case CommSystemFacade.STATUS_IPV4_SNAT_IPV6_UNKNOWN:
|
||||
case CommSystemFacade.STATUS_DIFFERENT:
|
||||
return NETWORK_STATUS.ERROR_SYMMETRIC_NAT;
|
||||
|
||||
case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
|
||||
case CommSystemFacade.STATUS_IPV4_FIREWALLED_IPV6_UNKNOWN:
|
||||
case CommSystemFacade.STATUS_IPV4_DISABLED_IPV6_FIREWALLED:
|
||||
if (_context.router().getRouterInfo().getTargetAddress("NTCP2") != null)
|
||||
case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
|
||||
if (_context.router().getRouterInfo().getTargetAddress("NTCP") != 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;
|
||||
return NETWORK_STATUS.FIREWALLED;
|
||||
|
||||
case CommSystemFacade.STATUS_HOSED:
|
||||
case CommSystemFacade.STATUS_HOSED:
|
||||
return NETWORK_STATUS.ERROR_UDP_PORT_IN_USE;
|
||||
|
||||
case CommSystemFacade.STATUS_DISCONNECTED:
|
||||
return NETWORK_STATUS.ERROR_NO_ACTIVE_PEERS_CHECK_CONNECTION_AND_FIREWALL;
|
||||
|
||||
case CommSystemFacade.STATUS_UNKNOWN: // fallthrough
|
||||
case CommSystemFacade.STATUS_IPV4_UNKNOWN_IPV6_OK:
|
||||
case CommSystemFacade.STATUS_IPV4_UNKNOWN_IPV6_FIREWALLED:
|
||||
case CommSystemFacade.STATUS_IPV4_DISABLED_IPV6_UNKNOWN:
|
||||
default:
|
||||
case CommSystemFacade.STATUS_UNKNOWN: // fallthrough
|
||||
default:
|
||||
ra = _context.router().getRouterInfo().getTargetAddress("SSU");
|
||||
if (ra == null && _context.router().getUptime() > 5 * 60 * 1000) {
|
||||
if (_context.commSystem().countActivePeers() <= 0)
|
||||
|
@ -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) {
|
||||
|
@ -2,13 +2,3 @@
|
||||
# This is for app context configuration of standalone i2psnark.
|
||||
# Almost all configuration settings are in i2psnark.config.d/i2psnark.config
|
||||
#
|
||||
# disable browser launch on startup
|
||||
#routerconsole.browser=/bin/false
|
||||
# disable browser launch on startup (Windows)
|
||||
#routerconsole.browser=NUL
|
||||
# change browser
|
||||
#routerconsole.browser=firefox
|
||||
# disable system tray
|
||||
#desktopgui.enabled=false
|
||||
# disable system tray notification popups
|
||||
#desktopgui.showNotifications=false
|
||||
|
@ -21,8 +21,6 @@
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<!-- jsp-api.jar only present for debian builds -->
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<!-- following jars only for standalone builds -->
|
||||
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
|
||||
</classpath>
|
||||
</depend>
|
||||
</target>
|
||||
@ -62,26 +60,18 @@
|
||||
<pathelement location="../../systray/java/build/systray.jar" />
|
||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
|
||||
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
|
||||
</classpath>
|
||||
</javac>
|
||||
</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 +108,7 @@
|
||||
<not>
|
||||
<isset property="war.uptodate" />
|
||||
</not>
|
||||
<isset property="git.available" />
|
||||
<isset property="mtn.available" />
|
||||
</and>
|
||||
</condition>
|
||||
</target>
|
||||
@ -206,30 +196,12 @@
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="checkwin">
|
||||
<condition property="iswin" >
|
||||
<os family="windows" />
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<target name="standalone" depends="standalone_prep, checkwin, zipit, zipwin">
|
||||
</target>
|
||||
|
||||
<target name="zipwin" depends="standalone_prep" if="iswin">
|
||||
<!-- doesn't support file permissions -->
|
||||
<zip destfile="build/i2psnark-standalone.zip">
|
||||
<zipfileset dir="./build/i2psnark/" fullpath="i2psnark" />
|
||||
<target name="standalone" depends="standalone_prep">
|
||||
<zip destfile="i2psnark-standalone.zip">
|
||||
<zipfileset dir="./dist/" prefix="i2psnark/" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="zipit" depends="standalone_prep" unless="iswin">
|
||||
<exec executable="zip" dir="build" failifexecutionfails="true" failonerror="true" >
|
||||
<arg value="-r" />
|
||||
<arg value="i2psnark-standalone.zip" />
|
||||
<arg value="i2psnark" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<!-- make a fat jar for standalone -->
|
||||
<target name="standalone_jar" depends="war">
|
||||
<!-- set if unset -->
|
||||
@ -256,8 +228,6 @@
|
||||
<zipfileset src="../../ministreaming/java/build/mstreaming.jar" />
|
||||
<zipfileset src="../../streaming/java/build/streaming.jar" />
|
||||
<zipfileset src="../../systray/java/build/systray.jar" />
|
||||
<zipfileset src="../../../build/jbigi.jar" />
|
||||
<zipfileset src="../../desktopgui/dist/desktopgui.jar" />
|
||||
<!-- Countries translations. The i2psnark translations are in the war but it's easier to put these here -->
|
||||
<!-- 300KB just to translate "Brazil", but why not... -->
|
||||
<!--
|
||||
@ -270,17 +240,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}" />
|
||||
<!--
|
||||
Suppress JNI warning in JRE 24+, and eventual restriction
|
||||
See https://openjdk.org/jeps/472
|
||||
-->
|
||||
<attribute name="Enable-Native-Access" value="ALL-UNNAMED" />
|
||||
<!-- 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>
|
||||
@ -323,12 +286,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"
|
||||
@ -339,8 +296,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" />
|
||||
@ -351,32 +306,33 @@
|
||||
</target>
|
||||
|
||||
<target name="standalone_prep" depends="standalone_jar, standalone_war">
|
||||
<delete dir="./build/i2psnark" />
|
||||
<mkdir dir="./build/i2psnark" />
|
||||
<copy file="../launch-i2psnark" todir="./build/i2psnark/" />
|
||||
<chmod type="file" file="./build/i2psnark/launch-i2psnark" perm="+x" />
|
||||
<copy file="../launch-i2psnark.bat" todir="./build/i2psnark/" />
|
||||
<mkdir dir="./build/i2psnark/contexts" />
|
||||
<copy file="../standalone-context.xml" tofile="./build/i2psnark/contexts/context.xml" />
|
||||
<mkdir dir="./build/i2psnark/docroot" />
|
||||
<copy file="../standalone-index.html" tofile="./build/i2psnark/docroot/index.html" />
|
||||
<mkdir dir="./build/i2psnark/webapps" />
|
||||
<copy file="../i2psnark.war" tofile="./build/i2psnark/webapps/i2psnark.war" />
|
||||
<copy file="../jetty-i2psnark.xml" tofile="./build/i2psnark/jetty-i2psnark.xml" />
|
||||
<copy file="../i2psnark-appctx.config" tofile="./build/i2psnark/i2psnark-appctx.config" />
|
||||
<copy file="./build/i2psnark-standalone.jar" tofile="./build/i2psnark/i2psnark.jar" />
|
||||
<copy file="../readme-standalone.txt" tofile="./build/i2psnark/readme.txt" />
|
||||
<delete dir="./dist" />
|
||||
<mkdir dir="./dist" />
|
||||
<copy file="../launch-i2psnark" todir="./dist/" />
|
||||
<copy file="../launch-i2psnark.bat" todir="./dist/" />
|
||||
<mkdir dir="./dist/contexts" />
|
||||
<copy file="../standalone-context.xml" tofile="./dist/contexts/context.xml" />
|
||||
<mkdir dir="./dist/docroot" />
|
||||
<copy file="../standalone-index.html" tofile="./dist/docroot/index.html" />
|
||||
<mkdir dir="./dist/webapps" />
|
||||
<copy file="../i2psnark.war" tofile="./dist/webapps/i2psnark.war" />
|
||||
<copy file="../jetty-i2psnark.xml" tofile="./dist/jetty-i2psnark.xml" />
|
||||
<copy file="../i2psnark-appctx.config" tofile="./dist/i2psnark-appctx.config" />
|
||||
<copy file="./build/i2psnark-standalone.jar" tofile="./dist/i2psnark.jar" />
|
||||
<copy file="../readme-standalone.txt" tofile="./dist/readme.txt" />
|
||||
<!-- temp so announces work -->
|
||||
<copy file="../../../installer/resources/hosts.txt" tofile="./build/i2psnark/hosts.txt" />
|
||||
<copy todir="./build/i2psnark/licenses" >
|
||||
<copy file="../../../installer/resources/hosts.txt" tofile="./dist/hosts.txt" />
|
||||
<copy todir="./dist/licenses" >
|
||||
<fileset dir="../../../licenses" includes="LICENSE-GPLv2.txt, ABOUT-Jetty.html" />
|
||||
</copy>
|
||||
<mkdir dir="./build/i2psnark/logs" />
|
||||
<mkdir dir="./dist/logs" />
|
||||
</target>
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="./build" />
|
||||
<delete file="../i2psnark.war" />
|
||||
<delete file="./i2psnark-standalone.zip" />
|
||||
<delete dir="./dist" />
|
||||
</target>
|
||||
<target name="cleandep" depends="clean">
|
||||
</target>
|
||||
|
@ -129,12 +129,7 @@ do
|
||||
RC=1
|
||||
break
|
||||
fi
|
||||
# fixup Enumeration code for generics
|
||||
sed -e 's/Enumeration/Enumeration<String>/g' \
|
||||
-e 's/Object nextElement/String nextElement/g' \
|
||||
-e 's/return key/return (String) key/g' \
|
||||
$TDX/messages_$LG.java > $TDY/messages_$LG.java
|
||||
rm -f $TDX/messages_$LG.java
|
||||
mv $TDX/messages_$LG.java $TDY
|
||||
rm -rf $TD
|
||||
fi
|
||||
fi
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
@ -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 time PeerCoordinator.CHECK_PERIOD each 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>";
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -83,9 +83,4 @@ public interface CompleteListener {
|
||||
* @since 0.9.42
|
||||
*/
|
||||
public boolean shouldAutoStart();
|
||||
|
||||
/**
|
||||
* @since 0.9.62
|
||||
*/
|
||||
public BandwidthListener getBandwidthListener();
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.RouterRestartException;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
@ -132,13 +131,12 @@ class ConnectionAcceptor implements Runnable
|
||||
/**
|
||||
* Effectively unused, would only be called if we changed
|
||||
* I2CP host/port, which is hidden in the gui if in router context
|
||||
* FIXME this only works if already running
|
||||
*/
|
||||
public synchronized void restart() {
|
||||
Thread t = thread;
|
||||
if (t != null)
|
||||
t.interrupt();
|
||||
else
|
||||
startAccepting();
|
||||
}
|
||||
|
||||
public int getPort()
|
||||
@ -203,24 +201,6 @@ class ConnectionAcceptor implements Runnable
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
catch (RouterRestartException rre) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Waiting for router restart", rre);
|
||||
try {
|
||||
Thread.sleep(2*60*1000);
|
||||
} catch (InterruptedException ie) {}
|
||||
while (true) {
|
||||
if (_util.connected())
|
||||
break;
|
||||
if (_util.connect())
|
||||
break;
|
||||
try {
|
||||
Thread.sleep(60*1000);
|
||||
} catch (InterruptedException ie) { break; }
|
||||
}
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Router restarted");
|
||||
}
|
||||
catch (I2PException ioe)
|
||||
{
|
||||
int level = stop ? Log.WARN : Log.ERROR;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
@ -31,12 +23,10 @@ import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketEepGet;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.client.streaming.I2PSocketManager.DisconnectListener;
|
||||
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 +35,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;
|
||||
@ -59,7 +47,7 @@ import org.klomp.snark.dht.KRPC;
|
||||
* so we can run multiple instances of single Snarks
|
||||
* (but not multiple SnarkManagers, it is still static)
|
||||
*/
|
||||
public class I2PSnarkUtil implements DisconnectListener {
|
||||
public class I2PSnarkUtil {
|
||||
private final I2PAppContext _context;
|
||||
private final Log _log;
|
||||
private final String _baseName;
|
||||
@ -86,11 +74,7 @@ public class I2PSnarkUtil implements DisconnectListener {
|
||||
private boolean _areFilesPublic;
|
||||
private List<String> _openTrackers;
|
||||
private DHT _dht;
|
||||
private boolean _enableUDP = ENABLE_UDP_TRACKER;
|
||||
private UDPTrackerClient _udpTracker;
|
||||
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;
|
||||
@ -101,25 +85,23 @@ public class I2PSnarkUtil implements DisconnectListener {
|
||||
public static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond";
|
||||
public static final boolean DEFAULT_USE_DHT = true;
|
||||
public static final String EEPGET_USER_AGENT = "I2PSnark";
|
||||
private static final boolean ENABLE_UDP_TRACKER = true;
|
||||
private static final List<String> HIDDEN_I2CP_OPTS = Arrays.asList(new String[] {
|
||||
PROP_MAX_BW, "inbound.length", "outbound.length", "inbound.quantity", "outbound.quantity"
|
||||
});
|
||||
|
||||
|
||||
public I2PSnarkUtil(I2PAppContext ctx) {
|
||||
this(ctx, "i2psnark", null);
|
||||
this(ctx, "i2psnark");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param baseName generally "i2psnark"
|
||||
* @since Jetty 7
|
||||
*/
|
||||
public I2PSnarkUtil(I2PAppContext ctx, String baseName, DisconnectListener discon) {
|
||||
public I2PSnarkUtil(I2PAppContext ctx, String baseName) {
|
||||
_context = ctx;
|
||||
_log = _context.logManager().getLog(I2PSnarkUtil.class);
|
||||
_log = _context.logManager().getLog(Snark.class);
|
||||
_baseName = baseName;
|
||||
_discon = discon;
|
||||
_opts = new HashMap<String, String>();
|
||||
//setProxy("127.0.0.1", 4444);
|
||||
setI2CPConfig("127.0.0.1", I2PClient.DEFAULT_LISTEN_PORT, null);
|
||||
@ -257,11 +239,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
|
||||
*/
|
||||
@ -339,62 +316,29 @@ public class I2PSnarkUtil implements DisconnectListener {
|
||||
opts.setProperty("i2p.streaming.disableRejectLogging", "true");
|
||||
if (opts.getProperty("i2p.streaming.answerPings") == null)
|
||||
opts.setProperty("i2p.streaming.answerPings", "false");
|
||||
if (opts.getProperty(I2PSocketOptions.PROP_PROFILE) == null)
|
||||
opts.setProperty(I2PSocketOptions.PROP_PROFILE, Integer.toString(I2PSocketOptions.PROFILE_BULK));
|
||||
if (opts.getProperty(I2PClient.PROP_SIGTYPE) == null)
|
||||
opts.setProperty(I2PClient.PROP_SIGTYPE, "EdDSA_SHA512_Ed25519");
|
||||
if (opts.getProperty("i2cp.leaseSetEncType") == null)
|
||||
opts.setProperty("i2cp.leaseSetEncType", "4");
|
||||
opts.setProperty("i2cp.leaseSetEncType", "4,0");
|
||||
// assume compressed content
|
||||
if (opts.getProperty(I2PClient.PROP_GZIP) == null)
|
||||
opts.setProperty(I2PClient.PROP_GZIP, "false");
|
||||
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
||||
if (_manager != null) {
|
||||
if (_manager != null)
|
||||
_startedTime = _context.clock().now();
|
||||
if (_discon != null)
|
||||
_manager.addDisconnectListener(this);
|
||||
}
|
||||
_connecting = false;
|
||||
}
|
||||
if (_shouldUseDHT && _manager != null && _dht == null)
|
||||
_dht = new KRPC(_context, _baseName, _manager.getSession());
|
||||
if (_enableUDP &&_manager != null) {
|
||||
if (_udpTracker == null)
|
||||
_udpTracker = new UDPTrackerClient(_context, _manager.getSession(), this);
|
||||
_udpTracker.start();
|
||||
}
|
||||
return (_manager != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* DisconnectListener interface
|
||||
* @since 0.9.53
|
||||
*/
|
||||
public void sessionDisconnected() {
|
||||
synchronized(this) {
|
||||
_manager = null;
|
||||
_connecting = false;
|
||||
if (_dht != null) {
|
||||
_dht.stop();
|
||||
_dht = null;
|
||||
}
|
||||
}
|
||||
if (_discon != null)
|
||||
_discon.sessionDisconnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null if disabled or not started
|
||||
* @since 0.8.4
|
||||
*/
|
||||
public DHT getDHT() { return _dht; }
|
||||
|
||||
/**
|
||||
* @return null if disabled or not started
|
||||
* @since 0.9.14
|
||||
*/
|
||||
public UDPTrackerClient getUDPTrackerClient() { return _udpTracker; }
|
||||
|
||||
public boolean connected() { return _manager != null; }
|
||||
|
||||
/** @since 0.9.1 */
|
||||
@ -417,10 +361,6 @@ public class I2PSnarkUtil implements DisconnectListener {
|
||||
_dht.stop();
|
||||
_dht = null;
|
||||
}
|
||||
if (_udpTracker != null) {
|
||||
_udpTracker.stop();
|
||||
_udpTracker = null;
|
||||
}
|
||||
_startedTime = 0;
|
||||
I2PSocketManager mgr = _manager;
|
||||
// FIXME this can cause race NPEs elsewhere
|
||||
@ -597,9 +537,6 @@ public class I2PSnarkUtil implements DisconnectListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full Base64 of Destination
|
||||
*/
|
||||
public String getOurIPString() {
|
||||
Destination dest = getMyDestination();
|
||||
if (dest != null)
|
||||
@ -771,16 +708,6 @@ public class I2PSnarkUtil implements DisconnectListener {
|
||||
return _shouldUseDHT;
|
||||
}
|
||||
|
||||
/** @since 0.9.67 */
|
||||
public void setUDPEnabled(boolean yes) {
|
||||
_enableUDP = yes;
|
||||
}
|
||||
|
||||
/** @since 0.9.67 */
|
||||
public boolean udpEnabled() {
|
||||
return _enableUDP;
|
||||
}
|
||||
|
||||
/** @since 0.9.31 */
|
||||
public void setRatingsEnabled(boolean yes) {
|
||||
_enableRatings = yes;
|
||||
@ -876,90 +803,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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
@ -82,9 +82,8 @@ public class MetaInfo
|
||||
* @param created_by may be null
|
||||
* @param url_list may be null
|
||||
* @param comment may be null
|
||||
* @since public since 0.9.53, was package private
|
||||
*/
|
||||
public MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
|
||||
MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
|
||||
int piece_length, byte[] piece_hashes, long length, boolean privateTorrent,
|
||||
List<List<String>> announce_list, String created_by, List<String> url_list, String comment)
|
||||
{
|
||||
@ -97,7 +96,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,72 +116,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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will not change infohash.
|
||||
* Retains creation date of old MetaInfo if nonzero.
|
||||
*
|
||||
* @param new_announce may be null
|
||||
* @param new_announce_list may be null
|
||||
* @param new_comment may be null
|
||||
* @param new_created_by may be null
|
||||
* @param new_url_list may be null
|
||||
* @since 0.9.64
|
||||
*/
|
||||
public MetaInfo(MetaInfo old, String new_announce, List<List<String>> new_announce_list, String new_comment,
|
||||
String new_created_by, List<String> new_url_list)
|
||||
{
|
||||
this.announce = new_announce;
|
||||
this.info_hash = old.info_hash;
|
||||
this.name = old.name;
|
||||
this.name_utf8 = old.name_utf8;
|
||||
this.files = old.files;
|
||||
this.files_utf8 = old.files_utf8;
|
||||
this.attributes = old.attributes;
|
||||
this.lengths = old.lengths;
|
||||
this.piece_length = old.piece_length;
|
||||
this.piece_hashes = old.piece_hashes;
|
||||
this.length = old.length;
|
||||
this.privateTorrent = old.privateTorrent;
|
||||
this.announce_list = new_announce_list;
|
||||
this.comment = new_comment;
|
||||
this.created_by = new_created_by;
|
||||
this.creation_date = old.creation_date > 0 ? old.creation_date : I2PAppContext.getGlobalContext().clock().now();
|
||||
this.url_list = new_url_list;
|
||||
this.infoMap = old.infoMap;
|
||||
this.infoBytesLength = old.infoBytesLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@ -207,7 +143,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.
|
||||
@ -249,20 +185,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
|
||||
@ -320,11 +247,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");
|
||||
@ -516,12 +442,9 @@ public class MetaInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the piece hashes.
|
||||
*
|
||||
* @return not a copy, do not modify
|
||||
* @since public since 0.9.53, was package private
|
||||
* Returns the piece hashes. Only used by storage so package local.
|
||||
*/
|
||||
public byte[] getPieceHashes()
|
||||
byte[] getPieceHashes()
|
||||
{
|
||||
return piece_hashes;
|
||||
}
|
||||
@ -541,14 +464,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;
|
||||
}
|
||||
|
||||
@ -801,19 +716,18 @@ public class MetaInfo
|
||||
if (infoMap != null)
|
||||
return Collections.unmodifiableMap(infoMap);
|
||||
// we should only get here if serving a magnet on a torrent we created
|
||||
// or on edit torrent save
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Creating new infomap", new Exception());
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Creating new infomap", new Exception());
|
||||
// otherwise we must create it
|
||||
Map<String, BEValue> info = new HashMap<String, BEValue>();
|
||||
info.put("name", new BEValue(DataHelper.getUTF8(name)));
|
||||
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));
|
||||
@ -891,7 +805,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) {
|
||||
@ -946,7 +860,10 @@ public class MetaInfo
|
||||
String an = announce != null ? announce : meta.getAnnounce();
|
||||
String cm = comment != null ? comment : meta.getComment();
|
||||
List<String> urls = url_list != null ? url_list : meta.getWebSeedURLs();
|
||||
MetaInfo meta2 = new MetaInfo(meta, an, meta.getAnnounceList(), cm, cb, urls);
|
||||
// changes/adds creation date
|
||||
MetaInfo meta2 = new MetaInfo(an, meta.getName(), null, meta.getFiles(), meta.getLengths(),
|
||||
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");
|
||||
if (net.i2p.util.FileUtil.copy(from, to, true, false)) {
|
||||
|
@ -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 + ')';
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user