i2p: Drop app as it has not been available in Debian for a while

Closes: #1528.
Closes: #2041.
Closes: #2438.

- In Bullseye and Bookworm the app is not available.

- i2pd (written is C++) is available in Debian, but it is not a drop-in
replacement for i2p. First, it is only a client. Then has a differently
philosophy of not integrating apps inside it and let outside apps connect to it.
If i2pd is ever added to FreedomBox, it has to be added as a new app with no
possibility of migration from an unlikely old setups.

- Updated wiki pages to remove references to I2P.

Tests:

- Looked for all string references to 'i2p'.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2024-12-15 09:54:36 -08:00 committed by James Valleroy
parent 11aa36f6ca
commit e523a83f1a
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
23 changed files with 6 additions and 1247 deletions

View File

@ -8,5 +8,4 @@ very-long-line-length-in-source-file * [doc/manual/*.raw.wiki:*]
very-long-line-length-in-source-file * [plinth/modules/deluge/tests/data/sample.torrent:*]
very-long-line-length-in-source-file * [plinth/modules/transmission/tests/data/sample.torrent:*]
very-long-line-length-in-source-file * [doc/visual_design/FreedomBox-Logo.7z:*]
very-long-line-length-in-source-file * [plinth/modules/i2p/tests/data/router.config:*]
very-long-line-length-in-source-file * [COPYING.md:*]

View File

@ -172,12 +172,12 @@ MANUAL_PAGES = ('Apache_userdir', 'APU', 'Backups', 'BananaPro', 'BeagleBone',
'DateTime', 'Debian', 'Deluge', 'Developer', 'Diagnostics',
'Download', 'DynamicDNS', 'ejabberd', 'Firewall',
'freedombox-manual', 'GettingHelp', 'GitWeb', 'Hardware',
'I2P', 'Ikiwiki', 'Infinoted', 'Introduction', 'JSXC',
'LetsEncrypt', 'Maker', 'MatrixSynapse', 'MediaWiki',
'Minetest', 'MiniDLNA', 'Mumble', 'NameServices', 'Networks',
'OpenVPN', 'OrangePiZero', 'PageKite', 'pcDuino3',
'Performance', 'PineA64+', 'PioneerEdition', 'Plinth', 'Power',
'Privoxy', 'Quassel', 'QuickStart', 'Radicale', 'RaspberryPi2',
'Ikiwiki', 'Infinoted', 'Introduction', 'JSXC', 'LetsEncrypt',
'Maker', 'MatrixSynapse', 'MediaWiki', 'Minetest', 'MiniDLNA',
'Mumble', 'NameServices', 'Networks', 'OpenVPN',
'OrangePiZero', 'PageKite', 'pcDuino3', 'Performance',
'PineA64+', 'PioneerEdition', 'Plinth', 'Power', 'Privoxy',
'Quassel', 'QuickStart', 'Radicale', 'RaspberryPi2',
'RaspberryPi3B+', 'RaspberryPi3B', 'RaspberryPi4B',
'ReleaseNotes', 'Rock64', 'RockPro64', 'Roundcube', 'Samba',
'Searx', 'SecureShell', 'Security', 'ServiceDiscovery',

View File

@ -1,122 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""FreedomBox app to configure I2P."""
from django.utils.translation import gettext_lazy as _
from plinth import app as app_module
from plinth import frontpage, menu
from plinth.config import DropinConfigs
from plinth.daemon import Daemon
from plinth.modules.apache.components import Webserver
from plinth.modules.backups.components import BackupRestore
from plinth.modules.firewall.components import (Firewall,
FirewallLocalProtection)
from plinth.modules.i2p.resources import FAVORITES
from plinth.modules.users.components import UsersAndGroups
from plinth.package import Packages
from . import manifest, privileged
_description = [
_('The Invisible Internet Project is an anonymous network layer intended '
'to protect communication from censorship and surveillance. I2P '
'provides anonymity by sending encrypted traffic through a '
'volunteer-run network distributed around the world.'),
_('Find more information about I2P on their project '
'<a href="https://geti2p.net" target="_blank">homepage</a>.'),
_('The first visit to the provided web interface will initiate the '
'configuration process.')
]
tunnels_to_manage = {
'I2P HTTP Proxy': 'i2p-http-proxy-freedombox',
'I2P HTTPS Proxy': 'i2p-https-proxy-freedombox',
'Irc2P': 'i2p-irc-freedombox'
}
class I2PApp(app_module.App):
"""FreedomBox app for I2P."""
app_id = 'i2p'
_version = 3
def __init__(self) -> None:
"""Create components for the app."""
super().__init__()
groups = {'i2p': _('Manage I2P application')}
info = app_module.Info(app_id=self.app_id, version=self._version,
name=_('I2P'), icon_filename='i2p',
short_description=_('Anonymity Network'),
description=_description, manual_page='I2P',
clients=manifest.clients, tags=manifest.tags)
self.add(info)
menu_item = menu.Menu('menu-i2p', info.name, info.short_description,
info.icon_filename, 'i2p:index',
parent_url_name='apps')
self.add(menu_item)
shortcut = frontpage.Shortcut('shortcut-i2p', info.name,
short_description=info.short_description,
icon=info.icon_filename, url='/i2p/',
clients=info.clients,
login_required=True,
allowed_groups=list(groups))
self.add(shortcut)
packages = Packages('packages-i2p', ['i2p'])
self.add(packages)
dropin_configs = DropinConfigs('dropin-configs-i2p', [
'/etc/apache2/conf-available/i2p-freedombox.conf',
])
self.add(dropin_configs)
firewall = Firewall('firewall-i2p-web', info.name,
ports=['http', 'https'], is_external=True)
self.add(firewall)
firewall = Firewall('firewall-i2p-proxies', _('I2P Proxy'),
ports=tunnels_to_manage.values(),
is_external=False)
self.add(firewall)
firewall_local_protection = FirewallLocalProtection(
'firewall-local-protection-i2p', ['7657'])
self.add(firewall_local_protection)
webserver = Webserver('webserver-i2p', 'i2p-freedombox',
urls=['https://{host}/i2p/'])
self.add(webserver)
daemon = Daemon('daemon-i2p', 'i2p', listen_ports=[(7657, 'tcp6')])
self.add(daemon)
users_and_groups = UsersAndGroups('users-and-groups-i2p',
groups=groups)
self.add(users_and_groups)
backup_restore = BackupRestore('backup-restore-i2p', **manifest.backup)
self.add(backup_restore)
def setup(self, old_version):
"""Install and configure the app."""
super().setup(old_version)
if not old_version:
self.disable()
# Add favorites to the configuration
for fav in FAVORITES:
privileged.add_favorite(fav['name'], fav['url'],
fav.get('description'),
fav.get('icon'))
# Tunnels to all interfaces
for tunnel in tunnels_to_manage:
privileged.set_tunnel_property(tunnel, 'interface', '0.0.0.0')
self.enable()

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>I2P HTTP Proxy</short>
<description>The Invisible Internet Project is an anonymous network layer intended to protect communication from censorship and surveillance. I2P provides anonymity by sending encrypted traffic through a volunteer-run network distributed around the world. Enable this if a running an I2P server with HTTP proxy and wish to connect into the I2P network to browse eepsites.</description>
<port protocol="tcp" port="4444"/>
</service>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>I2P HTTPS Proxy</short>
<description>The Invisible Internet Project is an anonymous network layer intended to protect communication from censorship and surveillance. I2P provides anonymity by sending encrypted traffic through a volunteer-run network distributed around the world. Enable this if a running an I2P server with HTTPS proxy and wish to connect into the I2P network to browse eepsites.</description>
<port protocol="tcp" port="4445"/>
</service>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>I2P IRC Tunnel</short>
<description>The Invisible Internet Project is an anonymous network layer intended to protect communication from censorship and surveillance. I2P provides anonymity by sending encrypted traffic through a volunteer-run network distributed around the world. Enable this if a running an I2P server with IRC tunnel and wish to access the Irc2P network.</description>
<port protocol="tcp" port="6668"/>
</service>

View File

@ -1,30 +0,0 @@
##
## On all sites, provide I2P on a default path: /i2p
##
## Requires the following Apache modules to be enabled:
## mod_headers
## mod_proxy
## mod_proxy_http
## mod_proxy_html
##
<Location /i2p>
# Disable compression
# As soon as it has to be chunked, it doesn't work
RequestHeader unset Accept-Encoding
ProxyPass http://localhost:7657
ProxyPassReverse http://localhost:7657
# Rewrite absolute urls from i2p to pass through apache
ProxyHTMLEnable On
ProxyHTMLURLMap / /i2p/
Include includes/freedombox-single-sign-on.conf
<IfModule mod_auth_pubtkt.c>
TKTAuthToken "admin" "i2p"
</IfModule>
</Location>
# Catch some other root i2p addresses
# These are most likely generated by javascript
RedirectMatch "^/(i2p[^/]+.*)" "/i2p/$1"

View File

@ -1 +0,0 @@
plinth.modules.i2p

View File

@ -1,232 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Various helpers for the I2P app.
"""
import os
import re
from collections import OrderedDict
import augeas
I2P_CONF_DIR = '/var/lib/i2p/i2p-config'
FILE_TUNNEL_CONF = os.path.join(I2P_CONF_DIR, 'i2ptunnel.config')
TUNNEL_IDX_REGEX = re.compile(r'tunnel.(\d+).name$')
I2P_ROUTER_CONF = os.path.join(I2P_CONF_DIR, 'router.config')
class TunnelEditor():
"""Helper to edit I2P tunnel configuration file using augeas.
:type aug: augeas.Augeas
"""
def __init__(self, conf_filename=None, idx=None):
self.conf_filename = conf_filename or FILE_TUNNEL_CONF
self.idx = idx
self.aug = None
@property
def lines(self):
"""Return lines from configuration file."""
if self.aug:
return self.aug.match('/files{}/*'.format(self.conf_filename))
return []
def read_conf(self):
"""Load an instance of Augeaus for processing APT configuration.
Chainable method.
"""
self.aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
augeas.Augeas.NO_MODL_AUTOLOAD)
self.aug.set('/augeas/load/Properties/lens', 'Properties.lns')
self.aug.set('/augeas/load/Properties/incl[last() + 1]',
self.conf_filename)
self.aug.load()
return self
def write_conf(self):
"""Write changes to the configuration file to disk.
Chainable method.
"""
self.aug.save()
return self
def set_tunnel_idx(self, name):
"""Finds the index of the tunnel with the given name.
Chainable method.
:type name: basestring
"""
for prop in self.aug.match('/files{}/*'.format(self.conf_filename)):
match = TUNNEL_IDX_REGEX.search(prop)
if match and self.aug.get(prop) == name:
self.idx = int(match.group(1))
return self
raise ValueError('No tunnel called {}'.format(name))
def calc_prop_path(self, tunnel_prop):
"""Calculates the property name as found in the properties files.
:type tunnel_prop: str
:rtype: basestring
"""
calced_prop_path = \
'/files{filepath}/tunnel.{idx}.{tunnel_prop}'.format(
idx=self.idx,
tunnel_prop=tunnel_prop,
filepath=self.conf_filename)
return calced_prop_path
def set_tunnel_prop(self, tunnel_prop, value):
"""Updates a tunnel's property.
The idx has to be set and the property has to exist in the config file
and belong to the tunnel's properties.
See calc_prop_path.
Chainable method.
:param tunnel_prop:
:type tunnel_prop: str
:param value:
:type value: basestring | int
:return:
:rtype:
"""
if self.idx is None:
raise ValueError(
'Please init the tunnel index before calling this method')
calc_prop_path = self.calc_prop_path(tunnel_prop)
self.aug.set(calc_prop_path, value)
return self
def __getitem__(self, tunnel_prop):
ret = self.aug.get(self.calc_prop_path(tunnel_prop))
if ret is None:
raise KeyError('Unknown property {}'.format(tunnel_prop))
return ret
def __setitem__(self, tunnel_prop, value):
self.aug.set(self.calc_prop_path(tunnel_prop), value)
class RouterEditor():
"""Helper to edit I2P router configuration file using augeas.
:type aug: augeas.Augeas
"""
FAVORITE_PROP = 'routerconsole.favorites'
FAVORITE_TUPLE_SIZE = 4
def __init__(self, filename=None):
self.conf_filename = filename or I2P_ROUTER_CONF
self.aug = None
def read_conf(self):
"""Load an instance of Augeaus for processing APT configuration.
Chainable method.
"""
self.aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
augeas.Augeas.NO_MODL_AUTOLOAD)
self.aug.set('/augeas/load/Properties/lens', 'Properties.lns')
self.aug.set('/augeas/load/Properties/incl[last() + 1]',
self.conf_filename)
self.aug.load()
return self
def write_conf(self):
"""Write changes to the configuration file to disk.
Chainable method.
"""
self.aug.save()
return self
@property
def favorite_property(self):
"""Return the favourites property from configuration file."""
return '/files{filename}/{prop}'.format(filename=self.conf_filename,
prop=self.FAVORITE_PROP)
def add_favorite(self, name, url, description=None, icon=None):
"""Add a favorite to the router configuration file.
Favorites are in a single string and separated by ','. none of the
incoming params can therefore use commas. I2P replaces the commas by
dots.
That's ok for the name and description, but not for the url and icon.
:type name: basestring
:type url: basestring
:type description: basestring
:type icon: basestring
"""
if not description:
description = ''
if not icon:
icon = '/themes/console/images/eepsite.png'
if ',' in url:
raise ValueError('URL cannot contain commas')
if ',' in icon:
raise ValueError('Icon cannot contain commas')
name = name.replace(',', '.')
description = description.replace(',', '.')
prop = self.favorite_property
favorites = self.aug.get(prop) or ''
new_favorite = '{name},{description},{url},{icon},'.format(
name=name, description=description, url=url, icon=icon)
self.aug.set(prop, favorites + new_favorite)
return self
def get_favorites(self):
"""Return list of favorites."""
favs_string = self.aug.get(self.favorite_property) or ''
favs_split = favs_string.split(',')
# There's a trailing comma --> 1 extra
favs_len = len(favs_split)
if favs_len > 0:
favs_split = favs_split[:-1]
favs_len = len(favs_split)
if favs_len % self.FAVORITE_TUPLE_SIZE:
raise SyntaxError("Invalid number of fields in favorite line")
favs = OrderedDict()
for index in range(0, favs_len, self.FAVORITE_TUPLE_SIZE):
next_index = index + self.FAVORITE_TUPLE_SIZE
name, description, url, icon = favs_split[index:next_index]
favs[url] = {
'name': name,
'description': description,
'icon': icon
}
return favs

View File

@ -1,43 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Application manifest for I2P.
"""
from django.utils.translation import gettext_lazy as _
_package_id = 'net.geti2p.i2p'
_download_url = 'https://geti2p.net/download'
clients = [{
'name':
_('I2P'),
'platforms': [{
'type': 'web',
'url': '/i2p/'
}, {
'type': 'package',
'format': 'deb',
'name': 'i2p',
}, {
'type': 'download',
'os': 'gnu-linux',
'url': _download_url,
}, {
'type': 'download',
'os': 'macos',
'url': _download_url,
}, {
'type': 'download',
'os': 'windows',
'url': _download_url,
}]
}]
backup = {
'secrets': {
'directories': ['/var/lib/i2p/i2p-config']
},
'services': ['i2p']
}
tags = [_('Anonymity network'), _('Censorship resistance')]

View File

@ -1,24 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Configure I2P."""
from plinth.actions import privileged
from plinth.modules.i2p.helpers import RouterEditor, TunnelEditor
@privileged
def set_tunnel_property(name: str, property_: str, value: str):
"""Modify the configuration file for a certain tunnel."""
editor = TunnelEditor()
editor \
.read_conf() \
.set_tunnel_idx(name) \
.set_tunnel_prop(property_, value) \
.write_conf()
@privileged
def add_favorite(name: str, url: str, description: str | None,
icon: str | None):
"""Add a favorite to router.config."""
editor = RouterEditor()
editor.read_conf().add_favorite(name, url, description, icon).write_conf()

View File

@ -1,111 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Pre-defined list of favorites for I2P and some additional favorites.
"""
DEFAULT_FAVORITES = [{
'name': 'anoncoin.i2p',
'description': 'The Anoncoin project',
'icon': '/themes/console/images/anoncoin_32.png',
'url': 'http://anoncoin.i2p/'
}, {
'name': 'Dev Builds',
'description': 'Development builds of I2P',
'icon': '/themes/console/images/script_gear.png',
'url': 'http://bobthebuilder.i2p/'
}, {
'name': 'Dev Forum',
'description': 'Development forum',
'icon': '/themes/console/images/group_gear.png',
'url': 'http://zzz.i2p/'
}, {
'name': 'echelon.i2p',
'description': 'I2P Applications',
'icon': '/themes/console/images/box_open.png',
'url': 'http://echelon.i2p/'
}, {
'name': 'exchanged.i2p',
'description': 'Anonymous cryptocurrency exchange',
'icon': '/themes/console/images/exchanged.png',
'url': 'http://exchanged.i2p/'
}, {
'name': 'I2P Bug Reports',
'description': 'Bug tracker',
'icon': '/themes/console/images/bug.png',
'url': 'http://trac.i2p2.i2p/report/1'
}, {
'name': 'I2P FAQ',
'description': 'Frequently Asked Questions',
'icon': '/themes/console/images/question.png',
'url': 'http://i2p-projekt.i2p/faq'
}, {
'name': 'I2P Forum',
'description': 'Community forum',
'icon': '/themes/console/images/group.png',
'url': 'http://i2pforum.i2p/'
}, {
'name': 'I2P Plugins',
'description': 'Add-on directory',
'icon': '/themes/console/images/info/plugin_link.png',
'url': 'http://i2pwiki.i2p/index.php?title=Plugins'
}, {
'name': 'I2P Technical Docs',
'description': 'Technical documentation',
'icon': '/themes/console/images/education.png',
'url': 'http://i2p-projekt.i2p/how'
}, {
'name': 'I2P Wiki',
'description': 'Anonymous wiki - share the knowledge',
'icon': '/themes/console/images/i2pwiki_logo.png',
'url': 'http://i2pwiki.i2p/'
}, {
'name': 'Planet I2P',
'description': 'I2P News',
'icon': '/themes/console/images/world.png',
'url': 'http://planet.i2p/'
}, {
'name': 'PrivateBin',
'description': 'Encrypted I2P Pastebin',
'icon': '/themes/console/images/paste_plain.png',
'url': 'http://paste.crypthost.i2p/'
}, {
'name': 'Project Website',
'description': 'I2P home page',
'icon': '/themes/console/images/info_rhombus.png',
'url': 'http://i2p-projekt.i2p/'
}, {
'name': 'stats.i2p',
'description': 'I2P Network Statistics',
'icon': '/themes/console/images/chart_line.png',
'url': 'http://stats.i2p/cgi-bin/dashboard.cgi'
}, {
'name': 'The Tin Hat',
'description': 'Privacy guides and tutorials',
'icon': '/themes/console/images/thetinhat.png',
'url': 'http://secure.thetinhat.i2p/'
}, {
'name': 'Trac Wiki',
'description': '',
'icon': '/themes/console/images/billiard_marker.png',
'url': 'http://trac.i2p2.i2p/'
}]
ADDITIONAL_FAVORITES = [
{
'name': 'Searx instance',
'url': 'http://ransack.i2p'
},
{
'name': 'Torrent tracker',
'url': 'http://tracker2.postman.i2p'
},
{
'name': 'YaCy Legwork',
'url': 'http://legwork.i2p'
},
{
'name': 'YaCy Seeker',
'url': 'http://seeker.i2p'
},
]
FAVORITES = DEFAULT_FAVORITES + ADDITIONAL_FAVORITES

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,201 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46667 135.46666"
version="1.1"
id="svg5311"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="i2p.svg"
inkscape:export-filename="/home/bunny/work/freedombox/i2p/logo.png"
inkscape:export-xdpi="158.14484"
inkscape:export-ydpi="158.14484">
<title
id="title4548">I2P</title>
<defs
id="defs5305" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="469.30791"
inkscape:cy="298.89334"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0.2"
fit-margin-bottom="0"
inkscape:window-width="2165"
inkscape:window-height="1223"
inkscape:window-x="426"
inkscape:window-y="282"
inkscape:window-maximized="0"
units="px" />
<metadata
id="metadata5308">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>I2P</dc:title>
<cc:license
rdf:resource="https://www.gnu.org/licenses/agpl-3.0.en.html" />
<dc:creator>
<cc:Agent>
<dc:title>Sunil Mohan Adapa &lt;sunil@medhas.org&gt;</dc:title>
</cc:Agent>
</dc:creator>
<dc:date>2019-04-01</dc:date>
<dc:description />
<dc:source>https://commons.wikimedia.org/wiki/File:I2P_logo.svg</dc:source>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-70.574828,-22.744926)">
<g
id="g4343"
transform="matrix(1.6671598,0,0,1.6671598,-47.084684,-118.59077)">
<g
transform="matrix(1.5533984,0,0,1.5533984,-113.33574,24.244873)"
id="g5041">
<path
d="m 125.47315,47.54207 a 3.540375,3.540375 0 1 1 -7.08075,0 3.540375,3.540375 0 1 1 7.08075,0 z"
id="path3798-3"
style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1.46127701"
inkscape:connector-curvature="0" />
<path
d="m 125.47315,59.2592 a 3.540375,3.540375 0 1 1 -7.08075,0 3.540375,3.540375 0 1 1 7.08075,0 z"
id="path3800-6"
style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1.46127701"
inkscape:connector-curvature="0" />
<path
d="m 125.47315,70.97627 a 3.540375,3.540375 0 1 1 -7.08075,0 3.540375,3.540375 0 1 1 7.08075,0 z"
id="path3802-7"
style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1.46127701"
inkscape:connector-curvature="0" />
<path
d="m 125.47315,82.69341 a 3.540375,3.540375 0 1 1 -7.08075,0 3.540375,3.540375 0 1 1 7.08075,0 z"
id="path3804-5"
style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1.46127701"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-8.0673233,-4.3621223e-4)"
id="g6025">
<path
d="m 107.20556,98.097074 a 5.499614,5.4996023 0 1 1 -10.999228,0 5.499614,5.4996023 0 1 1 10.999228,0 z"
id="path3873-0"
style="fill:#ebed02;fill-opacity:1;stroke:none;stroke-width:2.269943"
inkscape:connector-curvature="0" />
<path
d="m 107.20556,116.29841 a 5.499614,5.4996023 0 1 1 -10.999228,0 5.499614,5.4996023 0 1 1 10.999228,0 z"
id="path3875-9"
style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:2.269943"
inkscape:connector-curvature="0" />
<path
d="m 107.20556,134.49965 a 5.499614,5.4996023 0 1 1 -10.999228,0 5.499614,5.4996023 0 1 1 10.999228,0 z"
id="path3877-3"
style="fill:#ebed02;fill-opacity:1;stroke:none;stroke-width:2.269943"
inkscape:connector-curvature="0" />
<path
d="m 107.20556,152.70099 a 5.499614,5.4996023 0 1 1 -10.999228,0 5.499614,5.4996023 0 1 1 10.999228,0 z"
id="path3879-6"
style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:2.269943"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(8.5383197,0.00534911)"
id="g6019">
<path
d="m 125.72828,98.096947 a 5.4996129,5.4996129 0 1 1 -10.99922,0 5.4996129,5.4996129 0 1 1 10.99922,0 z"
id="path3921-0"
style="fill:#16ff0e;fill-opacity:0.85882353;stroke:none;stroke-width:2.26994538"
inkscape:connector-curvature="0" />
<path
d="m 125.72828,116.29832 a 5.4996129,5.4996129 0 1 1 -10.99922,0 5.4996129,5.4996129 0 1 1 10.99922,0 z"
id="path3923-6"
style="fill:#ebed02;fill-opacity:1;stroke:none;stroke-width:2.26994538"
inkscape:connector-curvature="0" />
<path
d="m 125.72828,134.49959 a 5.4996129,5.4996129 0 1 1 -10.99922,0 5.4996129,5.4996129 0 1 1 10.99922,0 z"
id="path3925-2"
style="fill:#16ff0e;fill-opacity:1;stroke:none;stroke-width:2.26994538"
inkscape:connector-curvature="0" />
<path
d="m 125.72828,152.70098 a 5.4996129,5.4996129 0 1 1 -10.99922,0 5.4996129,5.4996129 0 1 1 10.99922,0 z"
id="path3927-6"
style="fill:#ebed02;fill-opacity:1;stroke:none;stroke-width:2.26994538"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.5533984,0,0,1.5533984,-324.6688,22.140315)"
id="g5169">
<path
d="m 306.74654,48.896879 a 3.540375,3.540375 0 1 1 -7.08075,0 3.540375,3.540375 0 1 1 7.08075,0 z"
id="path3953-1"
style="fill:#16ff0e;fill-opacity:1;stroke:none;stroke-width:1.46127701"
inkscape:connector-curvature="0" />
<path
d="m 306.74654,60.614009 a 3.540375,3.540375 0 1 1 -7.08075,0 3.540375,3.540375 0 1 1 7.08075,0 z"
id="path3955-8"
style="fill:#16ff0e;fill-opacity:1;stroke:none;stroke-width:1.46127701"
inkscape:connector-curvature="0" />
<path
d="m 306.74654,72.331079 a 3.540375,3.540375 0 1 1 -7.08075,0 3.540375,3.540375 0 1 1 7.08075,0 z"
id="path3957-7"
style="fill:#16ff0e;fill-opacity:1;stroke:none;stroke-width:1.46127701"
inkscape:connector-curvature="0" />
<path
d="m 306.74654,84.048219 a 3.540375,3.540375 0 1 1 -7.08075,0 3.540375,3.540375 0 1 1 7.08075,0 z"
id="path3959-9"
style="fill:#16ff0e;fill-opacity:1;stroke:none;stroke-width:1.46127701"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(35.695276,-0.1044443)"
id="g6013">
<path
d="m 81.007144,98.201083 a 5.499615,5.4996033 0 1 1 -10.99923,0 5.499615,5.4996033 0 1 1 10.99923,0 z"
id="path3873-0-7"
style="fill:#ebed02;fill-opacity:1;stroke:none;stroke-width:2.269943"
inkscape:connector-curvature="0" />
<path
d="m 81.007144,134.60366 a 5.499615,5.4996033 0 1 1 -10.99923,0 5.499615,5.4996033 0 1 1 10.99923,0 z"
id="path3877-3-5"
style="fill:#ebed02;fill-opacity:1;stroke:none;stroke-width:2.269943"
inkscape:connector-curvature="0" />
<path
d="m 81.007137,116.40233 a 5.499613,5.499613 0 1 1 -10.99922,0 5.499613,5.499613 0 1 1 10.99922,0 z"
id="path3923-6-9"
style="fill:#ebed02;fill-opacity:1;stroke:none;stroke-width:2.26994538"
inkscape:connector-curvature="0" />
<path
d="m 81.007137,152.80499 a 5.499613,5.499613 0 1 1 -10.99922,0 5.499613,5.499613 0 1 1 10.99922,0 z"
id="path3927-6-2"
style="fill:#ebed02;fill-opacity:1;stroke:none;stroke-width:2.26994538"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -1,37 +0,0 @@
{% extends "app.html" %}
{% comment %}
# SPDX-License-Identifier: AGPL-3.0-or-later
{% endcomment %}
{% load bootstrap %}
{% load i18n %}
{% block configuration %}
{{ block.super }}
<h3>{% trans "I2P Proxies and Tunnels" %}</h3>
{% for line in proxies_description %}
<p>{{ line|safe }}</p>
{% endfor %}
<p>
<a class="btn btn-primary" target="_blank" role="button"
href="/i2p/i2ptunnel/"
{{ is_enabled|yesno:',disabled="disabled"' }}>
{% trans "Launch" %}
</a>
</p>
<h3>{% trans "Anonymous Torrents" %}</h3>
{% for line in torrents_description %}
<p>{{ line|safe }}</p>
{% endfor %}
<p>
<a class="btn btn-primary" target="_blank" role="button"
href="/i2p/i2psnark/"
{{ is_enabled|yesno:',disabled="disabled"' }}>
{% trans "Launch" %}
</a>
</p>
{% endblock %}

View File

@ -1,8 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Common parts for all I2P tests.
"""
from pathlib import Path
DATA_DIR = Path(__file__).parent / 'data'

View File

@ -1,192 +0,0 @@
# NOTE: This I2P config file must use UTF-8 encoding
tunnel.0.description=HTTP proxy for browsing eepsites and the web
tunnel.0.interface=127.0.0.1
tunnel.0.listenPort=4444
tunnel.0.name=I2P HTTP Proxy
tunnel.0.option.i2cp.closeIdleTime=1800000
tunnel.0.option.i2cp.closeOnIdle=false
tunnel.0.option.i2cp.delayOpen=false
tunnel.0.option.i2cp.destination.sigType=EdDSA_SHA512_Ed25519
tunnel.0.option.i2cp.newDestOnResume=false
tunnel.0.option.i2cp.reduceIdleTime=900000
tunnel.0.option.i2cp.reduceOnIdle=true
tunnel.0.option.i2cp.reduceQuantity=1
tunnel.0.option.i2p.streaming.connectDelay=1000
tunnel.0.option.i2ptunnel.httpclient.SSLOutproxies=false.i2p
tunnel.0.option.i2ptunnel.httpclient.allowInternalSSL=true
tunnel.0.option.i2ptunnel.httpclient.jumpServers=http://stats.i2p/cgi-bin/jump.cgi?a=,http://no.i2p/jump/,http://i2pjump.i2p/jump/
tunnel.0.option.i2ptunnel.httpclient.sendAccept=false
tunnel.0.option.i2ptunnel.httpclient.sendReferer=false
tunnel.0.option.i2ptunnel.httpclient.sendUserAgent=false
tunnel.0.option.i2ptunnel.useLocalOutproxy=false
tunnel.0.option.inbound.backupQuantity=0
tunnel.0.option.inbound.length=3
tunnel.0.option.inbound.lengthVariance=0
tunnel.0.option.inbound.nickname=shared clients
tunnel.0.option.inbound.quantity=2
tunnel.0.option.outbound.backupQuantity=0
tunnel.0.option.outbound.length=3
tunnel.0.option.outbound.lengthVariance=0
tunnel.0.option.outbound.nickname=shared clients
tunnel.0.option.outbound.priority=10
tunnel.0.option.outbound.quantity=2
tunnel.0.option.outproxyAuth=false
tunnel.0.option.persistentClientKey=false
tunnel.0.option.sslManuallySet=true
tunnel.0.option.useSSL=false
tunnel.0.proxyList=false.i2p
tunnel.0.sharedClient=true
tunnel.0.startOnLoad=true
tunnel.0.type=httpclient
tunnel.1.description=IRC tunnel to access the Irc2P network
tunnel.1.i2cpHost=127.0.0.1
tunnel.1.i2cpPort=7654
tunnel.1.interface=127.0.0.1
tunnel.1.listenPort=6668
tunnel.1.name=Irc2P
tunnel.1.option.crypto.lowTagThreshold=14
tunnel.1.option.crypto.tagsToSend=20
tunnel.1.option.i2cp.closeIdleTime=1200000
tunnel.1.option.i2cp.closeOnIdle=true
tunnel.1.option.i2cp.delayOpen=true
tunnel.1.option.i2cp.destination.sigType=ECDSA_SHA256_P256
tunnel.1.option.i2cp.newDestOnResume=false
tunnel.1.option.i2cp.reduceIdleTime=600000
tunnel.1.option.i2cp.reduceOnIdle=true
tunnel.1.option.i2cp.reduceQuantity=1
tunnel.1.option.i2p.streaming.connectDelay=1000
tunnel.1.option.i2p.streaming.maxWindowSize=16
tunnel.1.option.inbound.length=3
tunnel.1.option.inbound.lengthVariance=0
tunnel.1.option.inbound.nickname=Irc2P
tunnel.1.option.outbound.length=3
tunnel.1.option.outbound.lengthVariance=0
tunnel.1.option.outbound.nickname=Irc2P
tunnel.1.option.outbound.priority=15
tunnel.1.sharedClient=false
tunnel.1.startOnLoad=true
tunnel.1.targetDestination=irc.00.i2p:6667,irc.postman.i2p:6667,irc.echelon.i2p:6667
tunnel.1.type=ircclient
tunnel.2.description=I2P Monotone Server
tunnel.2.i2cpHost=127.0.0.1
tunnel.2.i2cpPort=7654
tunnel.2.interface=127.0.0.1
tunnel.2.listenPort=8998
tunnel.2.name=mtn.i2p-projekt.i2p
tunnel.2.option.i2cp.destination.sigType=EdDSA_SHA512_Ed25519
tunnel.2.option.i2cp.reduceIdleTime=900000
tunnel.2.option.i2cp.reduceOnIdle=true
tunnel.2.option.i2cp.reduceQuantity=1
tunnel.2.option.inbound.backupQuantity=0
tunnel.2.option.inbound.length=3
tunnel.2.option.inbound.lengthVariance=0
tunnel.2.option.inbound.nickname=shared clients
tunnel.2.option.inbound.quantity=2
tunnel.2.option.outbound.backupQuantity=0
tunnel.2.option.outbound.length=3
tunnel.2.option.outbound.lengthVariance=0
tunnel.2.option.outbound.nickname=shared clients
tunnel.2.option.outbound.quantity=2
tunnel.2.sharedClient=true
tunnel.2.startOnLoad=false
tunnel.2.targetDestination=mtn.i2p-projekt.i2p:4691
tunnel.2.type=client
tunnel.3.description=My eepsite
tunnel.3.i2cpHost=127.0.0.1
tunnel.3.i2cpPort=7654
tunnel.3.name=I2P webserver
tunnel.3.option.i2cp.destination.sigType=7
tunnel.3.option.i2p.streaming.limitAction=http
tunnel.3.option.i2p.streaming.maxConcurrentStreams=20
tunnel.3.option.i2p.streaming.maxConnsPerDay=100
tunnel.3.option.i2p.streaming.maxConnsPerHour=40
tunnel.3.option.i2p.streaming.maxConnsPerMinute=10
tunnel.3.option.i2p.streaming.maxTotalConnsPerMinute=25
tunnel.3.option.inbound.length=3
tunnel.3.option.inbound.lengthVariance=0
tunnel.3.option.inbound.nickname=eepsite
tunnel.3.option.maxPosts=3
tunnel.3.option.maxTotalPosts=10
tunnel.3.option.outbound.length=3
tunnel.3.option.outbound.lengthVariance=0
tunnel.3.option.outbound.nickname=eepsite
tunnel.3.option.shouldBundleReplyInfo=false
tunnel.3.privKeyFile=eepsite/eepPriv.dat
tunnel.3.spoofedHost=mysite.i2p
tunnel.3.startOnLoad=false
tunnel.3.targetHost=127.0.0.1
tunnel.3.targetPort=7658
tunnel.3.type=httpserver
tunnel.4.description=smtp server
tunnel.4.i2cpHost=127.0.0.1
tunnel.4.i2cpPort=7654
tunnel.4.interface=127.0.0.1
tunnel.4.listenPort=7659
tunnel.4.name=smtp.postman.i2p
tunnel.4.option.i2cp.destination.sigType=EdDSA_SHA512_Ed25519
tunnel.4.option.i2cp.reduceIdleTime=900000
tunnel.4.option.i2cp.reduceOnIdle=true
tunnel.4.option.i2cp.reduceQuantity=1
tunnel.4.option.inbound.backupQuantity=0
tunnel.4.option.inbound.length=3
tunnel.4.option.inbound.lengthVariance=0
tunnel.4.option.inbound.nickname=shared clients
tunnel.4.option.inbound.quantity=2
tunnel.4.option.outbound.backupQuantity=0
tunnel.4.option.outbound.length=3
tunnel.4.option.outbound.lengthVariance=0
tunnel.4.option.outbound.nickname=shared clients
tunnel.4.option.outbound.quantity=2
tunnel.4.sharedClient=true
tunnel.4.startOnLoad=true
tunnel.4.targetDestination=smtp.postman.i2p:25
tunnel.4.type=client
tunnel.5.description=pop3 server
tunnel.5.i2cpHost=127.0.0.1
tunnel.5.i2cpPort=7654
tunnel.5.interface=127.0.0.1
tunnel.5.listenPort=7660
tunnel.5.name=pop3.postman.i2p
tunnel.5.option.i2cp.destination.sigType=EdDSA_SHA512_Ed25519
tunnel.5.option.i2cp.reduceIdleTime=900000
tunnel.5.option.i2cp.reduceOnIdle=true
tunnel.5.option.i2cp.reduceQuantity=1
tunnel.5.option.i2p.streaming.connectDelay=1000
tunnel.5.option.inbound.backupQuantity=0
tunnel.5.option.inbound.length=3
tunnel.5.option.inbound.lengthVariance=0
tunnel.5.option.inbound.nickname=shared clients
tunnel.5.option.inbound.quantity=2
tunnel.5.option.outbound.backupQuantity=0
tunnel.5.option.outbound.length=3
tunnel.5.option.outbound.lengthVariance=0
tunnel.5.option.outbound.nickname=shared clients
tunnel.5.option.outbound.quantity=2
tunnel.5.sharedClient=true
tunnel.5.startOnLoad=true
tunnel.5.targetDestination=pop.postman.i2p:110
tunnel.5.type=client
tunnel.6.description=HTTPS proxy for browsing eepsites and the web
tunnel.6.i2cpHost=127.0.0.1
tunnel.6.i2cpPort=7654
tunnel.6.interface=127.0.0.1
tunnel.6.listenPort=4445
tunnel.6.name=I2P HTTPS Proxy
tunnel.6.option.i2cp.reduceIdleTime=900000
tunnel.6.option.i2cp.reduceOnIdle=true
tunnel.6.option.i2cp.reduceQuantity=1
tunnel.6.option.i2p.streaming.connectDelay=1000
tunnel.6.option.inbound.backupQuantity=0
tunnel.6.option.inbound.length=3
tunnel.6.option.inbound.lengthVariance=0
tunnel.6.option.inbound.nickname=shared clients
tunnel.6.option.inbound.quantity=2
tunnel.6.option.outbound.backupQuantity=0
tunnel.6.option.outbound.length=3
tunnel.6.option.outbound.lengthVariance=0
tunnel.6.option.outbound.nickname=shared clients
tunnel.6.option.outbound.quantity=2
tunnel.6.proxyList=outproxy-tor.meeh.i2p
tunnel.6.sharedClient=true
tunnel.6.startOnLoad=true
tunnel.6.type=connectclient

View File

@ -1,23 +0,0 @@
# NOTE: This I2P config file must use UTF-8 encoding
i2np.lastIPChange=1555091394049
i2np.ntcp2.iv=i3yLM2tPW6QH5h4YYZ8EWQ==
i2np.ntcp2.sp=j1K18jMDa5SPH23R2cHMJ-dUyPdo~uooZp6Uz06qP0k=
i2np.udp.internalPort=18778
i2np.udp.port=18778
jbigi.lastProcessor=Haswell Celeron/Pentium w/ AVX model 60/64
router.blocklistVersion=1523108115000
router.firstInstalled=1555091372597
router.firstVersion=0.9.38
router.inboundPool.randomKey=c1BGKzCBpxYfsH0AiEMIS39zYWzyBuWO9lYTqeA91dk=
router.outboundPool.randomKey=Of0jkHuGeUAHr~NoIAQbY930fbYacb4NyX3CjbVKKFI=
router.passwordManager.migrated=true
router.previousVersion=0.9.38
router.startup.jetty9.migrated=true
router.updateDisabled=true
router.updateLastInstalled=1555091372597
routerconsole.country=
routerconsole.favorites=anoncoin.i2p,The Anoncoin project,http://anoncoin.i2p/,/themes/console/images/anoncoin_32.png,Dev Builds,Development builds of I2P,http://bobthebuilder.i2p/,/themes/console/images/script_gear.png,Dev Forum,Development forum,http://zzz.i2p/,/themes/console/images/group_gear.png,echelon.i2p,I2P Applications,http://echelon.i2p/,/themes/console/images/box_open.png,exchanged.i2p,Anonymous cryptocurrency exchange,http://exchanged.i2p/,/themes/console/images/exchanged.png,I2P Bug Reports,Bug tracker,http://trac.i2p2.i2p/report/1,/themes/console/images/bug.png,I2P FAQ,Frequently Asked Questions,http://i2p-projekt.i2p/faq,/themes/console/images/question.png,I2P Forum,Community forum,http://i2pforum.i2p/,/themes/console/images/group.png,I2P Plugins,Add-on directory,http://i2pwiki.i2p/index.php?title=Plugins,/themes/console/images/info/plugin_link.png,I2P Technical Docs,Technical documentation,http://i2p-projekt.i2p/how,/themes/console/images/education.png,I2P Wiki,Anonymous wiki - share the knowledge,http://i2pwiki.i2p/,/themes/console/images/i2pwiki_logo.png,Planet I2P,I2P News,http://planet.i2p/,/themes/console/images/world.png,PrivateBin,Encrypted I2P Pastebin,http://paste.crypthost.i2p/,/themes/console/images/paste_plain.png,Project Website,I2P home page,http://i2p-projekt.i2p/,/themes/console/images/info_rhombus.png,stats.i2p,I2P Network Statistics,http://stats.i2p/cgi-bin/dashboard.cgi,/themes/console/images/chart_line.png,The Tin Hat,Privacy guides and tutorials,http://secure.thetinhat.i2p/,/themes/console/images/thetinhat.png,Trac Wiki,,http://trac.i2p2.i2p/,/themes/console/images/billiard_marker.png,
routerconsole.lang=en
routerconsole.newsLastChecked=1555093599462
routerconsole.newsLastUpdated=1553195540000
routerconsole.welcomeWizardComplete=true

View File

@ -1,17 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Functional, browser based tests for i2p app.
"""
import pytest
from plinth.tests.functional import BaseAppTests
pytestmark = [pytest.mark.apps, pytest.mark.i2p]
class TestI2pApp(BaseAppTests):
app_name = 'i2p'
has_service = True
has_web = True
diagnostics_delay = 1

View File

@ -1,61 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Unit tests for helpers of I2P application.
"""
from pathlib import Path
import pytest
from plinth.modules.i2p.helpers import TunnelEditor
DATA_DIR = Path(__file__).parent / 'data'
TUNNEL_CONF_PATH = DATA_DIR / 'i2ptunnel.config'
TUNNEL_HTTP_NAME = 'I2P HTTP Proxy'
@pytest.fixture(name='editor')
def fixture_editor():
"""Setup editor for each test."""
return TunnelEditor(str(TUNNEL_CONF_PATH))
def test_reading_conf(editor):
"""Test reading configuration file."""
editor.read_conf()
assert len(editor.lines) > 1
def test_setting_idx(editor):
"""Test setting index for editing a tunnel."""
editor.read_conf()
assert editor.idx is None
editor.set_tunnel_idx(TUNNEL_HTTP_NAME)
assert editor.idx == 0
def test_setting_tunnel_props(editor):
"""Test setting a tunnel property."""
editor.read_conf()
editor.set_tunnel_idx('I2P HTTP Proxy')
interface = '0.0.0.0'
editor.set_tunnel_prop('interface', interface)
assert editor['interface'] == interface
def test_getting_nonexistent_props(editor):
"""Test getting nonexistent property."""
editor.read_conf()
editor.idx = 0
with pytest.raises(KeyError):
_ = editor['blabla'] # noqa
def test_setting_new_props(editor):
"""Test setting new properties."""
editor.read_conf()
editor.idx = 0
value = 'lol'
prop = 'blablabla'
editor[prop] = value
assert editor[prop] == value

View File

@ -1,73 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Test I2P router configuration editing helper.
"""
import pytest
from plinth.modules.i2p.helpers import RouterEditor
from plinth.modules.i2p.tests import DATA_DIR
ROUTER_CONF_PATH = str(DATA_DIR / 'router.config')
@pytest.fixture(name='editor')
def fixture_editor():
"""Return editor instance object for each test."""
return RouterEditor(ROUTER_CONF_PATH)
def test_count_favorites(editor):
"""Test counting favorites."""
editor.read_conf()
favorites = editor.get_favorites()
assert len(favorites.keys()) == 17
def test_add_normal_favorite(editor):
"""Test adding a normal favorite."""
editor.read_conf()
name = 'Somewhere'
url = 'http://somewhere-again.i2p'
description = "Just somewhere else"
editor.add_favorite(name, url, description)
favorites = editor.get_favorites()
assert url in favorites
favorite = favorites[url]
assert favorite['name'] == name
assert favorite['description'] == description
assert len(favorites) == 18
def test_add_favorite_with_comma(editor):
"""Test adding a favorite with common in its name."""
editor.read_conf()
name = 'Name,with,comma'
expected_name = name.replace(',', '.')
url = 'http://url-without-comma.i2p'
description = "Another,comma,to,play,with"
expected_description = description.replace(',', '.')
editor.add_favorite(name, url, description)
favorites = editor.get_favorites()
assert url in favorites
favorite = favorites[url]
assert favorite['name'] == expected_name
assert favorite['description'] == expected_description
assert len(favorites) == 18
def test_add_fav_to_empty_config(editor):
"""Test adding favorite to empty configuration."""
editor.conf_filename = '/tmp/inexistent.conf'
editor.read_conf()
assert not editor.get_favorites()
name = 'Test Favorite'
url = 'http://test-fav.i2p'
editor.add_favorite(name, url)
assert len(editor.get_favorites()) == 1

View File

@ -1,12 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
URLs for the I2P module.
"""
from django.urls import re_path
from plinth.modules.i2p import views
urlpatterns = [
re_path(r'^apps/i2p/$', views.I2PAppView.as_view(), name='index')
]

View File

@ -1,35 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Views for I2P application.
"""
from django.utils.translation import gettext_lazy as _
from plinth.views import AppView
class I2PAppView(AppView):
"""Serve configuration page."""
app_id = 'i2p'
template_name = 'i2p.html'
proxies_description = [
_('I2P lets you browse the Internet and hidden services (eepsites) '
'anonymously. For this, your browser, preferably the Tor Browser, '
'needs to be configured with a proxy.'),
_('By default HTTP, HTTPS and IRC proxies are available. Additional '
'proxies and tunnels may be configured using the tunnel '
'configuration interface.'),
]
torrents_description = [
_('I2P provides an application to download files anonymously in a '
'peer-to-peer network. Download files by adding torrents or '
'create a new torrent to share a file.'),
]
def get_context_data(self, **kwargs):
"""Return the context data for rendering the template view."""
context = super().get_context_data(**kwargs)
context['proxies_description'] = self.proxies_description
context['torrents_description'] = self.torrents_description
return context