propagate from branch 'i2p.i2p.zzz.test2' (head 5c1b78bd78845b0c8b90fbb60412c68e7dc4f3e6)

to branch 'i2p.i2p' (head 8bdc25c8e6f40491f20b533d94eacab012adba35)
This commit is contained in:
zzz
2013-10-13 11:48:12 +00:00
135 changed files with 19078 additions and 16810 deletions

View File

@ -77,6 +77,7 @@ trans.pt = apps/routerconsole/locale-news/messages_pt.po
trans.ru_RU = apps/routerconsole/locale-news/messages_ru.po trans.ru_RU = apps/routerconsole/locale-news/messages_ru.po
trans.sv_SE = apps/routerconsole/locale-news/messages_sv.po trans.sv_SE = apps/routerconsole/locale-news/messages_sv.po
trans.tr_TR = apps/routerconsole/locale-news/messages_tr.po trans.tr_TR = apps/routerconsole/locale-news/messages_tr.po
trans.zh_CN = apps/routerconsole/locale-news/messages_zh.po
[I2P.i2psnark] [I2P.i2psnark]
source_file = apps/i2psnark/locale/messages_en.po source_file = apps/i2psnark/locale/messages_en.po

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/bash
INST_DIR=directory INST_DIR=directory

View File

@ -44,6 +44,7 @@
<target name="bundle" unless="no.bundle"> <target name="bundle" unless="no.bundle">
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" /> <arg value="./bundle-messages.sh" />
</exec> </exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >

View File

@ -16,6 +16,10 @@ TMPFILE=build/javafiles.txt
export TZ=UTC export TZ=UTC
RC=0 RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ] if [ "$1" = "-p" ]
then then
POUPDATE=1 POUPDATE=1

View File

@ -130,6 +130,7 @@
<!-- Update the messages_*.po files. <!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true --> We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" /> <arg value="./bundle-messages.sh" />
</exec> </exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >

View File

@ -15,6 +15,10 @@ TMPFILE=build/javafiles.txt
export TZ=UTC export TZ=UTC
RC=0 RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ] if [ "$1" = "-p" ]
then then
POUPDATE=1 POUPDATE=1

View File

@ -193,6 +193,7 @@ public class SnarkManager implements CompleteListener {
if (_umgr != null) { if (_umgr != null) {
_uhandler = new UpdateHandler(_context, _umgr, SnarkManager.this); _uhandler = new UpdateHandler(_context, _umgr, SnarkManager.this);
_umgr.register(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT, 10); _umgr.register(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT, 10);
_umgr.register(_uhandler, UpdateType.ROUTER_SIGNED_SU3, UpdateMethod.TORRENT, 10);
_log.warn("Registering with update manager"); _log.warn("Registering with update manager");
} else { } else {
_log.warn("No update manager to register with"); _log.warn("No update manager to register with");
@ -210,6 +211,7 @@ public class SnarkManager implements CompleteListener {
if (_umgr != null && _uhandler != null) { if (_umgr != null && _uhandler != null) {
//_uhandler.shutdown(); //_uhandler.shutdown();
_umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT); _umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT);
_umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED_SU3, UpdateMethod.TORRENT);
} }
_running = false; _running = false;
_monitor.interrupt(); _monitor.interrupt();

View File

@ -42,10 +42,10 @@ class UpdateHandler implements Updater {
*/ */
public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources, public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources,
String id, String newVersion, long maxTime) { String id, String newVersion, long maxTime) {
if (type != UpdateType.ROUTER_SIGNED || if ((type != UpdateType.ROUTER_SIGNED && type != UpdateType.ROUTER_SIGNED_SU3) ||
method != UpdateMethod.TORRENT || updateSources.isEmpty()) method != UpdateMethod.TORRENT || updateSources.isEmpty())
return null; return null;
UpdateRunner update = new UpdateRunner(_context, _umgr, _smgr, updateSources, newVersion); UpdateRunner update = new UpdateRunner(_context, _umgr, _smgr, type, updateSources, newVersion);
_umgr.notifyProgress(update, "<b>" + _smgr.util().getString("Updating") + "</b>"); _umgr.notifyProgress(update, "<b>" + _smgr.util().getString("Updating") + "</b>");
return update; return update;
} }

View File

@ -22,6 +22,7 @@ class UpdateRunner implements UpdateTask, CompleteListener {
private final Log _log; private final Log _log;
private final UpdateManager _umgr; private final UpdateManager _umgr;
private final SnarkManager _smgr; private final SnarkManager _smgr;
private final UpdateType _type;
private final List<URI> _urls; private final List<URI> _urls;
private volatile boolean _isRunning; private volatile boolean _isRunning;
private volatile boolean _hasMetaInfo; private volatile boolean _hasMetaInfo;
@ -36,11 +37,12 @@ class UpdateRunner implements UpdateTask, CompleteListener {
private static final long CHECK_INTERVAL = 3*60*1000; private static final long CHECK_INTERVAL = 3*60*1000;
public UpdateRunner(I2PAppContext ctx, UpdateManager umgr, SnarkManager smgr, public UpdateRunner(I2PAppContext ctx, UpdateManager umgr, SnarkManager smgr,
List<URI> uris, String newVersion) { UpdateType type, List<URI> uris, String newVersion) {
_context = ctx; _context = ctx;
_log = ctx.logManager().getLog(getClass()); _log = ctx.logManager().getLog(getClass());
_umgr = umgr; _umgr = umgr;
_smgr = smgr; _smgr = smgr;
_type = type;
_urls = uris; _urls = uris;
_newVersion = newVersion; _newVersion = newVersion;
} }
@ -56,7 +58,7 @@ class UpdateRunner implements UpdateTask, CompleteListener {
} }
} }
public UpdateType getType() { return UpdateType.ROUTER_SIGNED; } public UpdateType getType() { return _type; }
public UpdateMethod getMethod() { return UpdateMethod.TORRENT; } public UpdateMethod getMethod() { return UpdateMethod.TORRENT; }
@ -111,7 +113,7 @@ class UpdateRunner implements UpdateTask, CompleteListener {
} }
_snark = _smgr.addMagnet(name, ih, trackerURL, true, true, this); _snark = _smgr.addMagnet(name, ih, trackerURL, true, true, this);
if (_snark != null) { if (_snark != null) {
updateStatus("<b>" + _smgr.util().getString("Updating from {0}", updateURL) + "</b>"); updateStatus("<b>" + _smgr.util().getString("Updating from {0}", linkify(updateURL)) + "</b>");
new Timeout(); new Timeout();
break; break;
} }
@ -292,6 +294,12 @@ class UpdateRunner implements UpdateTask, CompleteListener {
//////// end CompleteListener methods //////// end CompleteListener methods
private static String linkify(String url) {
String durl = url.length() <= 28 ? url :
url.substring(0, 25) + "&hellip;";
return "<a target=\"_blank\" href=\"" + url + "\"/>" + durl + "</a>";
}
private void updateStatus(String s) { private void updateStatus(String s) {
_umgr.notifyProgress(this, s); _umgr.notifyProgress(this, s);
} }

View File

@ -6,20 +6,21 @@
# Translators: # Translators:
# "blabla", 2011 # "blabla", 2011
# blabla <blabla@trash-mail.com>, 2012 # blabla <blabla@trash-mail.com>, 2012
# D.A. Loader <>, 2012 # D.A. Loader, 2012
# ducki2p <ducki2p@gmail.com>, 2011 # ducki2p <ducki2p@gmail.com>, 2011
# foo <foo@bar>, 2009 # foo <foo@bar>, 2009
# SteinQuadrat, 2013 # SteinQuadrat, 2013
# mixxy, 2011 # mixxy, 2011
# nextloop <ga25day@mytum.de>, 2013
# pirr <pirr@tormail.org>, 2012 # pirr <pirr@tormail.org>, 2012
# zeroflag <zeroflag@i2pmail.org>, 2013 # zeroflag <zeroflag@i2pmail.org>, 2013
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-07-02 17:23+0000\n" "POT-Creation-Date: 2013-09-26 21:33+0000\n"
"PO-Revision-Date: 2013-06-27 13:09+0000\n" "PO-Revision-Date: 2013-09-23 22:30+0000\n"
"Last-Translator: SteinQuadrat\n" "Last-Translator: nextloop <ga25day@mytum.de>\n"
"Language-Team: German (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: German (http://www.transifex.com/projects/p/I2P/language/"
"de/)\n" "de/)\n"
"Language: de\n" "Language: de\n"
@ -426,16 +427,16 @@ msgstr "I2P Tunnel öffnen ..."
msgid "Opening the I2P tunnel and starting all torrents." msgid "Opening the I2P tunnel and starting all torrents."
msgstr "Öffne den I2P-Tunnel und starte alle Torrents ..." msgstr "Öffne den I2P-Tunnel und starte alle Torrents ..."
#: ../java/src/org/klomp/snark/SnarkManager.java:1903 #: ../java/src/org/klomp/snark/SnarkManager.java:1911
msgid "Stopping all torrents and closing the I2P tunnel." msgid "Stopping all torrents and closing the I2P tunnel."
msgstr "Stoppe alle Torrents und beende den I2P-Tunnel." msgstr "Stoppe alle Torrents und beende den I2P-Tunnel."
#: ../java/src/org/klomp/snark/SnarkManager.java:1922 #: ../java/src/org/klomp/snark/SnarkManager.java:1930
msgid "Closing I2P tunnel after notifying trackers." msgid "Closing I2P tunnel after notifying trackers."
msgstr "Der I2P-Tunnel wird nach Benachrichtigung der Tracker geschlossen." msgstr "Der I2P-Tunnel wird nach Benachrichtigung der Tracker geschlossen."
#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #: ../java/src/org/klomp/snark/SnarkManager.java:1937
#: ../java/src/org/klomp/snark/SnarkManager.java:1940 #: ../java/src/org/klomp/snark/SnarkManager.java:1948
msgid "I2P tunnel closed." msgid "I2P tunnel closed."
msgstr "I2P-Tunnel geschlossen." msgstr "I2P-Tunnel geschlossen."
@ -600,9 +601,8 @@ msgid "Stop All"
msgstr "Stoppe alle" msgstr "Stoppe alle"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515
#, fuzzy
msgid "Start all stopped torrents" msgid "Start all stopped torrents"
msgstr "Torrent starten" msgstr "Alle angehaltenen Torrents fortsetzen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531
@ -1159,7 +1159,7 @@ msgid "Website URL"
msgstr "Webseiten-URL" msgstr "Webseiten-URL"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2016 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2016
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2567 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566
msgid "Open" msgid "Open"
msgstr "offen" msgstr "offen"
@ -1209,15 +1209,15 @@ msgstr "Tracker Liste"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2356 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2356
msgid "Comment" msgid "Comment"
msgstr "" msgstr "Kommentar"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2365 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2365
msgid "Created" msgid "Created"
msgstr "" msgstr "Erstellt"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2375 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2375
msgid "Created By" msgid "Created By"
msgstr "" msgstr "Erstellt von"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2385 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2385
msgid "Magnet link" msgid "Magnet link"
@ -1283,18 +1283,18 @@ msgstr "vollständig"
msgid "remaining" msgid "remaining"
msgstr "verbleibend" msgstr "verbleibend"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2594 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2592
msgid "High" msgid "High"
msgstr "hoch" msgstr "hoch"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2599 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2597
msgid "Normal" msgid "Normal"
msgstr "normal" msgstr "normal"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2604 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2602
msgid "Skip" msgid "Skip"
msgstr "auslassen" msgstr "auslassen"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2613 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2611
msgid "Save priorities" msgid "Save priorities"
msgstr "Prioritäten speichern" msgstr "Prioritäten speichern"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P i2psnark\n" "Project-Id-Version: I2P i2psnark\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-11 14:23+0000\n" "POT-Creation-Date: 2013-09-20 10:46+0000\n"
"PO-Revision-Date: 2010-06-15 14:09+0100\n" "PO-Revision-Date: 2010-06-15 14:09+0100\n"
"Last-Translator: duck <duck@mail.i2p>\n" "Last-Translator: duck <duck@mail.i2p>\n"
"Language-Team: duck <duck@mail.i2p>\n" "Language-Team: duck <duck@mail.i2p>\n"
@ -1100,7 +1100,7 @@ msgid "Website URL"
msgstr "" msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2016 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2016
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2567 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566
msgid "Open" msgid "Open"
msgstr "" msgstr ""
@ -1224,18 +1224,18 @@ msgstr ""
msgid "remaining" msgid "remaining"
msgstr "" msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2594 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2592
msgid "High" msgid "High"
msgstr "" msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2599 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2597
msgid "Normal" msgid "Normal"
msgstr "" msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2604 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2602
msgid "Skip" msgid "Skip"
msgstr "" msgstr ""
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2613 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2611
msgid "Save priorities" msgid "Save priorities"
msgstr "" msgstr ""

View File

@ -15,7 +15,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-11 14:29+0000\n" "POT-Creation-Date: 2013-09-20 10:24+0000\n"
"PO-Revision-Date: 2013-07-16 15:32+0000\n" "PO-Revision-Date: 2013-07-16 15:32+0000\n"
"Last-Translator: Boxoa590\n" "Last-Translator: Boxoa590\n"
"Language-Team: French (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: French (http://www.transifex.com/projects/p/I2P/language/"
@ -1152,7 +1152,7 @@ msgid "Website URL"
msgstr "URL du site web" msgstr "URL du site web"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2016 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2016
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2567 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566
msgid "Open" msgid "Open"
msgstr "Ouvrir le fichier" msgstr "Ouvrir le fichier"
@ -1276,18 +1276,18 @@ msgstr "complet"
msgid "remaining" msgid "remaining"
msgstr "restant" msgstr "restant"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2594 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2592
msgid "High" msgid "High"
msgstr "Haut" msgstr "Haut"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2599 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2597
msgid "Normal" msgid "Normal"
msgstr "Normal" msgstr "Normal"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2604 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2602
msgid "Skip" msgid "Skip"
msgstr "Ignorer" msgstr "Ignorer"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2613 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2611
msgid "Save priorities" msgid "Save priorities"
msgstr "Sauvegarder les priorités" msgstr "Sauvegarder les priorités"

View File

@ -15,7 +15,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-11 14:27+0000\n" "POT-Creation-Date: 2013-09-20 10:16+0000\n"
"PO-Revision-Date: 2013-07-12 16:38+0000\n" "PO-Revision-Date: 2013-07-12 16:38+0000\n"
"Last-Translator: varnav\n" "Last-Translator: varnav\n"
"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/I2P/" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/I2P/"
@ -1155,7 +1155,7 @@ msgid "Website URL"
msgstr "URL сайта" msgstr "URL сайта"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2016 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2016
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2567 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566
msgid "Open" msgid "Open"
msgstr "Открыть" msgstr "Открыть"
@ -1281,18 +1281,18 @@ msgstr "скачано"
msgid "remaining" msgid "remaining"
msgstr "осталось" msgstr "осталось"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2594 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2592
msgid "High" msgid "High"
msgstr "Высокий" msgstr "Высокий"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2599 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2597
msgid "Normal" msgid "Normal"
msgstr "Нормальный" msgstr "Нормальный"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2604 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2602
msgid "Skip" msgid "Skip"
msgstr "Пропустить" msgstr "Пропустить"
#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2613 #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2611
msgid "Save priorities" msgid "Save priorities"
msgstr "Сохранить приоритеты" msgstr "Сохранить приоритеты"

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ ogv = video/ogg
oga = audio/ogg oga = audio/ogg
rar = application/x-rar-compressed rar = application/x-rar-compressed
su2 = application/zip su2 = application/zip
su3 = application/zip
sud = application/zip sud = application/zip
tbz = application/x-bzip2 tbz = application/x-bzip2
txt = text/plain txt = text/plain

View File

@ -92,6 +92,7 @@
<!-- Update the messages_*.po files. <!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true --> We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" /> <arg value="./bundle-messages.sh" />
</exec> </exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >
@ -124,6 +125,7 @@
<!-- Update the messages_*.po files. <!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true --> We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages-proxy.sh" /> <arg value="./bundle-messages-proxy.sh" />
</exec> </exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >

View File

@ -15,6 +15,10 @@ TMPFILE=build/javafiles-proxy.txt
export TZ=UTC export TZ=UTC
RC=0 RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ] if [ "$1" = "-p" ]
then then
POUPDATE=1 POUPDATE=1

View File

@ -14,6 +14,9 @@ CLASS=net.i2p.i2ptunnel.web.messages
TMPFILE=build/javafiles.txt TMPFILE=build/javafiles.txt
export TZ=UTC export TZ=UTC
RC=0 RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC="${JAVA_HOME}/../bin/javac"
fi
if [ "$1" = "-p" ] if [ "$1" = "-p" ]
then then

View File

@ -5,21 +5,21 @@
# #
# Translators: # Translators:
# blabla, 2011 # blabla, 2011
# blabla <blabla@trash-mail.com>, 2011-2012
# D.A. Loader <>, 2012 # D.A. Loader <>, 2012
# driz <driz@i2pmail.org>, 2012 # driz <driz@i2pmail.org>, 2012
# ducki2p <ducki2p@gmail.com>, 2011 # ducki2p <ducki2p@gmail.com>, 2011
# foo <foo@bar>, 2009 # foo <foo@bar>, 2009
# mixxy, 2011 # mixxy, 2011
# nextloop <ga25day@mytum.de>, 2013
# pirr <pirr@tormail.org>, 2012 # pirr <pirr@tormail.org>, 2012
# zeroflag <zeroflag@i2pmail.org>, 2013 # zeroflag <zeroflag@i2pmail.org>, 2013
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P i2ptunnel\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-07-13 18:49+0000\n" "POT-Creation-Date: 2013-09-26 21:33+0000\n"
"PO-Revision-Date: 2013-05-08 13:15+0000\n" "PO-Revision-Date: 2013-09-23 22:34+0000\n"
"Last-Translator: zeroflag <zeroflag@i2pmail.org>\n" "Last-Translator: nextloop <ga25day@mytum.de>\n"
"Language-Team: German (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: German (http://www.transifex.com/projects/p/I2P/language/"
"de/)\n" "de/)\n"
"Language: de\n" "Language: de\n"
@ -28,337 +28,339 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../java/build/Proxy.java:5 #: ../java/build/Proxy.java:5 ../java/build/Proxy.java:11
msgid "Proxy Authorization Required" msgid "Warning: Outproxy Not Found"
msgstr "Outproxy Autorisation"
#: ../java/build/Proxy.java:6
msgid "I2P HTTP Proxy Authorization Required"
msgstr "Outproxy Autorisation"
#: ../java/build/Proxy.java:7
msgid "This proxy is configured to require a username and password for access."
msgstr "" msgstr ""
#: ../java/build/Proxy.java:8 #: ../java/build/Proxy.java:6 ../java/build/Proxy.java:18
#, java-format #: ../java/build/Proxy.java:27 ../java/build/Proxy.java:40
msgid "" #: ../java/build/Proxy.java:49 ../java/build/Proxy.java:61
"Please enter your username and password, or check your {0}router " #: ../java/build/Proxy.java:69 ../java/build/Proxy.java:88
"configuration{1} or {2}I2PTunnel configuration{3}." #: ../java/build/Proxy.java:99 ../java/build/Proxy.java:111
msgstr "" #: ../java/build/Proxy.java:121
#: ../java/build/Proxy.java:9
#, java-format
msgid ""
"To disable authorization, remove the configuration {0}i2ptunnel.proxy."
"auth=basic{1}, then stop and restart the HTTP Proxy tunnel."
msgstr ""
#: ../java/build/Proxy.java:10 ../java/build/Proxy.java:16
msgid "Warning: No Outproxy Configured"
msgstr ""
#: ../java/build/Proxy.java:11 ../java/build/Proxy.java:20
#: ../java/build/Proxy.java:32 ../java/build/Proxy.java:44
#: ../java/build/Proxy.java:52 ../java/build/Proxy.java:61
#: ../java/build/Proxy.java:74 ../java/build/Proxy.java:83
#: ../java/build/Proxy.java:93 ../java/build/Proxy.java:103
#: ../java/build/Proxy.java:115
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:196 #: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:196
msgid "Router Console" msgid "Router Console"
msgstr "Routerkonsole" msgstr "Routerkonsole"
#: ../java/build/Proxy.java:12 ../java/build/Proxy.java:21 #: ../java/build/Proxy.java:7 ../java/build/Proxy.java:19
#: ../java/build/Proxy.java:33 ../java/build/Proxy.java:45 #: ../java/build/Proxy.java:28 ../java/build/Proxy.java:41
#: ../java/build/Proxy.java:53 ../java/build/Proxy.java:62 #: ../java/build/Proxy.java:50 ../java/build/Proxy.java:62
#: ../java/build/Proxy.java:75 ../java/build/Proxy.java:84 #: ../java/build/Proxy.java:70 ../java/build/Proxy.java:89
#: ../java/build/Proxy.java:94 ../java/build/Proxy.java:104 #: ../java/build/Proxy.java:100 ../java/build/Proxy.java:112
#: ../java/build/Proxy.java:116 #: ../java/build/Proxy.java:122
msgid "I2P Router Console" msgid "I2P Router Console"
msgstr "Routerkonsole" msgstr "Routerkonsole"
#: ../java/build/Proxy.java:13 ../java/build/Proxy.java:22 #: ../java/build/Proxy.java:8 ../java/build/Proxy.java:20
#: ../java/build/Proxy.java:34 ../java/build/Proxy.java:46 #: ../java/build/Proxy.java:29 ../java/build/Proxy.java:42
#: ../java/build/Proxy.java:54 ../java/build/Proxy.java:63 #: ../java/build/Proxy.java:51 ../java/build/Proxy.java:63
#: ../java/build/Proxy.java:76 ../java/build/Proxy.java:85 #: ../java/build/Proxy.java:71 ../java/build/Proxy.java:90
#: ../java/build/Proxy.java:95 ../java/build/Proxy.java:105 #: ../java/build/Proxy.java:101 ../java/build/Proxy.java:113
#: ../java/build/Proxy.java:117 #: ../java/build/Proxy.java:123
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197 #: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Configuration" msgid "Configuration"
msgstr "Einstellungen" msgstr "Einstellungen"
#: ../java/build/Proxy.java:14 ../java/build/Proxy.java:23 #: ../java/build/Proxy.java:9 ../java/build/Proxy.java:21
#: ../java/build/Proxy.java:35 ../java/build/Proxy.java:47 #: ../java/build/Proxy.java:30 ../java/build/Proxy.java:43
#: ../java/build/Proxy.java:55 ../java/build/Proxy.java:64 #: ../java/build/Proxy.java:52 ../java/build/Proxy.java:64
#: ../java/build/Proxy.java:77 ../java/build/Proxy.java:86 #: ../java/build/Proxy.java:72 ../java/build/Proxy.java:91
#: ../java/build/Proxy.java:96 ../java/build/Proxy.java:106 #: ../java/build/Proxy.java:102 ../java/build/Proxy.java:114
#: ../java/build/Proxy.java:118 #: ../java/build/Proxy.java:124
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197 #: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Help" msgid "Help"
msgstr "Hilfe" msgstr "Hilfe"
#: ../java/build/Proxy.java:15 ../java/build/Proxy.java:24 #: ../java/build/Proxy.java:10 ../java/build/Proxy.java:22
#: ../java/build/Proxy.java:36 ../java/build/Proxy.java:48 #: ../java/build/Proxy.java:31 ../java/build/Proxy.java:44
#: ../java/build/Proxy.java:56 ../java/build/Proxy.java:65 #: ../java/build/Proxy.java:53 ../java/build/Proxy.java:65
#: ../java/build/Proxy.java:78 ../java/build/Proxy.java:87 #: ../java/build/Proxy.java:73 ../java/build/Proxy.java:92
#: ../java/build/Proxy.java:97 ../java/build/Proxy.java:107 #: ../java/build/Proxy.java:103 ../java/build/Proxy.java:115
#: ../java/build/Proxy.java:119 #: ../java/build/Proxy.java:125
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197 #: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Addressbook" msgid "Addressbook"
msgstr "Adressbuch" msgstr "Adressbuch"
#: ../java/build/Proxy.java:17 #: ../java/build/Proxy.java:12
msgid ""
"Your request was for a site outside of I2P, but you have no HTTP outproxy "
"configured."
msgstr ""
#: ../java/build/Proxy.java:18
msgid "Please configure an outproxy in I2PTunnel."
msgstr ""
#: ../java/build/Proxy.java:19
msgid "Information: New Host Name"
msgstr ""
#: ../java/build/Proxy.java:25
msgid "Information: New Host Name with Address Helper"
msgstr ""
#: ../java/build/Proxy.java:26
msgid ""
"The address helper link you followed is for a new host name that is not in "
"your address book."
msgstr ""
#: ../java/build/Proxy.java:27
msgid "You may save this host name to your local address book."
msgstr ""
#: ../java/build/Proxy.java:28
msgid ""
"If you save it to your address book, you will not see this message again."
msgstr ""
#: ../java/build/Proxy.java:29
msgid ""
"If you do not save it, the host name will be forgotten after the next router "
"restart."
msgstr ""
#: ../java/build/Proxy.java:30
msgid ""
"If you do not wish to visit this host, click the \"back\" button on your "
"browser."
msgstr ""
#: ../java/build/Proxy.java:31 ../java/build/Proxy.java:37
msgid "Warning: Invalid Destination"
msgstr "lokales Ziel"
#: ../java/build/Proxy.java:38
msgid ""
"The eepsite destination specified was not valid, or was otherwise "
"unreachable."
msgstr ""
#: ../java/build/Proxy.java:39
msgid ""
"Perhaps you pasted in the wrong Base 64 string or the link you are following "
"is bad."
msgstr ""
#: ../java/build/Proxy.java:40
msgid "The I2P host could also be offline."
msgstr ""
#: ../java/build/Proxy.java:41 ../java/build/Proxy.java:123
#, java-format
msgid "You may want to {0}retry{1}."
msgstr ""
#: ../java/build/Proxy.java:42 ../java/build/Proxy.java:72
#: ../java/build/Proxy.java:113 ../java/build/Proxy.java:124
msgid "Could not find the following destination:"
msgstr "Tunnel Ziel"
#: ../java/build/Proxy.java:43 ../java/build/Proxy.java:49
msgid "Warning: Request Denied"
msgstr ""
#: ../java/build/Proxy.java:50
msgid "You attempted to connect to a non-I2P website or location."
msgstr ""
#: ../java/build/Proxy.java:51 ../java/build/Proxy.java:57
msgid "Warning: Invalid Request URI"
msgstr ""
#: ../java/build/Proxy.java:58
msgid "The request URI is invalid, and probably contains illegal characters."
msgstr ""
#: ../java/build/Proxy.java:59
msgid ""
"If you clicked a link, check the end of the URI for any characters the "
"browser has mistakenly added on."
msgstr ""
#: ../java/build/Proxy.java:60
msgid "Warning: Eepsite Unknown"
msgstr ""
#: ../java/build/Proxy.java:66
msgid "Warning: Eepsite Not Found in Addressbook"
msgstr ""
#: ../java/build/Proxy.java:67
msgid "The eepsite was not found in your router's addressbook."
msgstr ""
#: ../java/build/Proxy.java:68
msgid "Check the link or find a Base 32 or Base 64 address."
msgstr ""
#: ../java/build/Proxy.java:69
#, java-format
msgid "If you have the Base 64 address, {0}add it to your addressbook{1}."
msgstr ""
#: ../java/build/Proxy.java:70
msgid ""
"Otherwise, find a Base 32 or address helper link, or use a jump service link "
"below."
msgstr ""
#: ../java/build/Proxy.java:71
#, java-format
msgid ""
"Seeing this page often? See {0}the FAQ{1} for help in {2}adding some "
"subscriptions{3} to your addressbook."
msgstr ""
#: ../java/build/Proxy.java:73
msgid "Error: Request Denied"
msgstr ""
#: ../java/build/Proxy.java:79
msgid "Error: Local Access"
msgstr ""
#: ../java/build/Proxy.java:80
msgid "Your browser is misconfigured."
msgstr "Dein Browser unterstützt keine iFrames."
#: ../java/build/Proxy.java:81
msgid ""
"Do not use the proxy to access the router console, localhost, or local LAN "
"destinations."
msgstr ""
#: ../java/build/Proxy.java:82 ../java/build/Proxy.java:88
msgid "Warning: Non-HTTP Protocol"
msgstr ""
#: ../java/build/Proxy.java:89
msgid "The request uses a bad protocol."
msgstr ""
#: ../java/build/Proxy.java:90
#, java-format
msgid "The I2P HTTP Proxy supports {0}http://{1} requests ONLY."
msgstr ""
#: ../java/build/Proxy.java:91
#, java-format
msgid ""
"Other protocols such as {0}https://{1} and {0}ftp://{1} are not allowed."
msgstr ""
#: ../java/build/Proxy.java:92 ../java/build/Proxy.java:98
msgid "Warning: Bad Address Helper"
msgstr ""
#: ../java/build/Proxy.java:99
#, java-format
msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable."
msgstr ""
#: ../java/build/Proxy.java:100
msgid "It seems to be garbage data, or a mistyped Base 32 address."
msgstr ""
#: ../java/build/Proxy.java:101
msgid ""
"Check your URL to try and fix the helper key to be a valid Base 32 hostname "
"or Base 64 key."
msgstr ""
#: ../java/build/Proxy.java:102 ../java/build/Proxy.java:108
msgid "Warning: Outproxy Not Found"
msgstr ""
#: ../java/build/Proxy.java:109
msgid "The HTTP Outproxy was not found." msgid "The HTTP Outproxy was not found."
msgstr "Der HTTP-Proxy ist nicht bereit" msgstr "Der HTTP-Proxy ist nicht bereit"
#: ../java/build/Proxy.java:110 #: ../java/build/Proxy.java:13
msgid "" msgid ""
"It is offline, there is network congestion, or your router is not yet well-" "It is offline, there is network congestion, or your router is not yet well-"
"integrated with peers." "integrated with peers."
msgstr "" msgstr ""
#: ../java/build/Proxy.java:111 #: ../java/build/Proxy.java:14
#, java-format #, java-format
msgid "" msgid ""
"You may want to {0}retry{1} as this will randomly reselect an outproxy from " "You may want to {0}retry{1} as this will randomly reselect an outproxy from "
"the pool you have defined {2}here{3} (if you have more than one configured)." "the pool you have defined {2}here{3} (if you have more than one configured)."
msgstr "" msgstr ""
#: ../java/build/Proxy.java:112 #: ../java/build/Proxy.java:15
#, java-format #, java-format
msgid "" msgid ""
"If you continue to have trouble you may want to edit your outproxy list {0}" "If you continue to have trouble you may want to edit your outproxy list {0}"
"here{1}." "here{1}."
msgstr "" msgstr ""
#: ../java/build/Proxy.java:114 ../java/build/Proxy.java:120 #: ../java/build/Proxy.java:16 ../java/build/Proxy.java:38
msgid "Warning: Eepsite Unreachable" #: ../java/build/Proxy.java:59 ../java/build/Proxy.java:97
msgid "Could not find the following destination:"
msgstr "Tunnel Ziel"
#: ../java/build/Proxy.java:17
msgid "Error: Request Denied"
msgstr "" msgstr ""
#: ../java/build/Proxy.java:121 #: ../java/build/Proxy.java:23
msgid "The eepsite was not reachable." msgid "Error: Local Access"
msgstr "" msgstr ""
#: ../java/build/Proxy.java:122 #: ../java/build/Proxy.java:24
msgid "Your browser is misconfigured."
msgstr "Dein Browser unterstützt keine iFrames."
#: ../java/build/Proxy.java:25
msgid "" msgid ""
"The eepsite is offline, there is network congestion, or your router is not " "Do not use the proxy to access the router console, localhost, or local LAN "
"yet well-integrated with peers." "destinations."
msgstr "" msgstr ""
#: ../java/build/Proxy.java:125 ../java/build/Proxy.java:126 #: ../java/build/Proxy.java:26
msgid "Warning: Eepsite Unknown"
msgstr ""
#: ../java/build/Proxy.java:32
msgid "Warning: Eepsite Not Found in Addressbook"
msgstr ""
#: ../java/build/Proxy.java:33
msgid "The eepsite was not found in your router's addressbook."
msgstr ""
#: ../java/build/Proxy.java:34
msgid "Check the link or find a Base 32 or Base 64 address."
msgstr ""
#: ../java/build/Proxy.java:35
#, java-format
msgid "If you have the Base 64 address, {0}add it to your addressbook{1}."
msgstr ""
#: ../java/build/Proxy.java:36
msgid ""
"Otherwise, find a Base 32 or address helper link, or use a jump service link "
"below."
msgstr ""
#: ../java/build/Proxy.java:37
#, java-format
msgid ""
"Seeing this page often? See {0}the FAQ{1} for help in {2}adding some "
"subscriptions{3} to your addressbook."
msgstr ""
#: ../java/build/Proxy.java:39 ../java/build/Proxy.java:45
msgid "Warning: Invalid Request URI"
msgstr ""
#: ../java/build/Proxy.java:46
msgid "The request URI is invalid, and probably contains illegal characters."
msgstr ""
#: ../java/build/Proxy.java:47
msgid ""
"If you clicked a link, check the end of the URI for any characters the "
"browser has mistakenly added on."
msgstr ""
#: ../java/build/Proxy.java:48 ../java/build/Proxy.java:54
msgid "Warning: Invalid Destination"
msgstr "lokales Ziel"
#: ../java/build/Proxy.java:55
msgid ""
"The eepsite destination specified was not valid, or was otherwise "
"unreachable."
msgstr ""
#: ../java/build/Proxy.java:56
msgid ""
"Perhaps you pasted in the wrong Base 64 string or the link you are following "
"is bad."
msgstr ""
#: ../java/build/Proxy.java:57
msgid "The I2P host could also be offline."
msgstr ""
#: ../java/build/Proxy.java:58 ../java/build/Proxy.java:96
#, java-format
msgid "You may want to {0}retry{1}."
msgstr ""
#: ../java/build/Proxy.java:60 ../java/build/Proxy.java:66
msgid "Warning: Request Denied"
msgstr ""
#: ../java/build/Proxy.java:67
msgid "You attempted to connect to a non-I2P website or location."
msgstr ""
#: ../java/build/Proxy.java:68 ../java/build/Proxy.java:74
msgid "Warning: No Outproxy Configured"
msgstr ""
#: ../java/build/Proxy.java:75
msgid ""
"Your request was for a site outside of I2P, but you have no HTTP outproxy "
"configured."
msgstr ""
#: ../java/build/Proxy.java:76
msgid "Please configure an outproxy in I2PTunnel."
msgstr ""
#: ../java/build/Proxy.java:77 ../java/build/Proxy.java:78
msgid "Warning: Destination Key Conflict" msgid "Warning: Destination Key Conflict"
msgstr "" msgstr ""
#: ../java/build/Proxy.java:127 #: ../java/build/Proxy.java:79
msgid "" msgid ""
"The addresshelper link you followed specifies a different destination key " "The addresshelper link you followed specifies a different destination key "
"than a host entry in your host database." "than a host entry in your host database."
msgstr "" msgstr ""
#: ../java/build/Proxy.java:128 #: ../java/build/Proxy.java:80
msgid "" msgid ""
"Someone could be trying to impersonate another eepsite, or people have given " "Someone could be trying to impersonate another eepsite, or people have given "
"two eepsites identical names." "two eepsites identical names."
msgstr "" msgstr ""
#: ../java/build/Proxy.java:129 #: ../java/build/Proxy.java:81
msgid "" msgid ""
"You can resolve the conflict by considering which key you trust, and either " "You can resolve the conflict by considering which key you trust, and either "
"discarding the addresshelper link, discarding the host entry from your host " "discarding the addresshelper link, discarding the host entry from your host "
"database, or naming one of them differently." "database, or naming one of them differently."
msgstr "" msgstr ""
#: ../java/build/Proxy.java:82
msgid "Proxy Authorization Required"
msgstr "Outproxy Autorisation"
#: ../java/build/Proxy.java:83
msgid "I2P HTTP Proxy Authorization Required"
msgstr "Outproxy Autorisation"
#: ../java/build/Proxy.java:84
msgid "This proxy is configured to require a username and password for access."
msgstr "Dieser Proxy kann nur mit Benutzername und Passwort erreicht werde."
#: ../java/build/Proxy.java:85
#, java-format
msgid ""
"Please enter your username and password, or check your {0}router "
"configuration{1} or {2}I2PTunnel configuration{3}."
msgstr ""
"Bitte Benutzername und Passwort eingeben, oder überprüfe die {0}Router-"
"Einstellungen{1} oder die {2}I2P-Tunnel Einstellungen{3}"
#: ../java/build/Proxy.java:86
#, java-format
msgid ""
"To disable authorization, remove the configuration {0}i2ptunnel.proxy."
"auth=basic{1}, then stop and restart the HTTP Proxy tunnel."
msgstr ""
#: ../java/build/Proxy.java:87 ../java/build/Proxy.java:93
msgid "Warning: Eepsite Unreachable"
msgstr ""
#: ../java/build/Proxy.java:94
msgid "The eepsite was not reachable."
msgstr ""
#: ../java/build/Proxy.java:95
msgid ""
"The eepsite is offline, there is network congestion, or your router is not "
"yet well-integrated with peers."
msgstr ""
#: ../java/build/Proxy.java:98
msgid "Information: New Host Name"
msgstr ""
#: ../java/build/Proxy.java:104
msgid "Information: New Host Name with Address Helper"
msgstr ""
#: ../java/build/Proxy.java:105
msgid ""
"The address helper link you followed is for a new host name that is not in "
"your address book."
msgstr ""
#: ../java/build/Proxy.java:106
msgid "You may save this host name to your local address book."
msgstr ""
#: ../java/build/Proxy.java:107
msgid ""
"If you save it to your address book, you will not see this message again."
msgstr ""
#: ../java/build/Proxy.java:108
msgid ""
"If you do not save it, the host name will be forgotten after the next router "
"restart."
msgstr ""
#: ../java/build/Proxy.java:109
msgid ""
"If you do not wish to visit this host, click the \"back\" button on your "
"browser."
msgstr ""
#: ../java/build/Proxy.java:110 ../java/build/Proxy.java:116
msgid "Warning: Bad Address Helper"
msgstr ""
#: ../java/build/Proxy.java:117
#, java-format
msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable."
msgstr ""
#: ../java/build/Proxy.java:118
msgid "It seems to be garbage data, or a mistyped Base 32 address."
msgstr ""
#: ../java/build/Proxy.java:119
msgid ""
"Check your URL to try and fix the helper key to be a valid Base 32 hostname "
"or Base 64 key."
msgstr ""
#: ../java/build/Proxy.java:120 ../java/build/Proxy.java:126
msgid "Warning: Non-HTTP Protocol"
msgstr ""
#: ../java/build/Proxy.java:127
msgid "The request uses a bad protocol."
msgstr ""
#: ../java/build/Proxy.java:128
#, java-format
msgid "The I2P HTTP Proxy supports {0}http://{1} requests ONLY."
msgstr ""
#: ../java/build/Proxy.java:129
#, java-format
msgid ""
"Other protocols such as {0}https://{1} and {0}ftp://{1} are not allowed."
msgstr ""
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572
msgid "This seems to be a bad destination:" msgid "This seems to be a bad destination:"
msgstr "Dies scheint kein gültiges Ziel zu sein:" msgstr "Dies scheint kein gültiges Ziel zu sein:"
@ -415,7 +417,7 @@ msgstr "{0} im privaten Adressbuch speichern und auf die Eepseite weiterleiten"
msgid "HTTP Outproxy" msgid "HTTP Outproxy"
msgstr "HTTP-Outproxy" msgstr "HTTP-Outproxy"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1185 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1216
msgid "" msgid ""
"Click a link below to look for an address helper by using a \"jump\" service:" "Click a link below to look for an address helper by using a \"jump\" service:"
msgstr "" msgstr ""
@ -423,7 +425,7 @@ msgstr ""
"Adresshelfer von einem \"Sprung\"-Service:" "Adresshelfer von einem \"Sprung\"-Service:"
#. Translators: parameter is a host name #. Translators: parameter is a host name
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1221 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1224
#, java-format #, java-format
msgid "{0} jump service" msgid "{0} jump service"
msgstr "Weiterleitungsdienst {0}" msgstr "Weiterleitungsdienst {0}"

View File

@ -4,16 +4,16 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers # To contribute translations, see http://www.i2p2.de/newdevelopers
# #
# Translators: # Translators:
# Boxoa590, 2012-2013
# ducki2p <ducki2p@gmail.com>, 2011 # ducki2p <ducki2p@gmail.com>, 2011
# foo <foo@bar>, 2009 # foo <foo@bar>, 2009
# Boxoa590, 2013 # Boxoa590, 2013
# Boxoa590, 2012
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P i2ptunnel\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-11 14:30+0000\n" "POT-Creation-Date: 2013-09-20 10:24+0000\n"
"PO-Revision-Date: 2013-05-29 21:00+0000\n" "PO-Revision-Date: 2013-08-18 18:06+0000\n"
"Last-Translator: Boxoa590\n" "Last-Translator: Boxoa590\n"
"Language-Team: French (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: French (http://www.transifex.com/projects/p/I2P/language/"
"fr/)\n" "fr/)\n"
@ -25,7 +25,7 @@ msgstr ""
#: ../java/build/Proxy.java:5 ../java/build/Proxy.java:11 #: ../java/build/Proxy.java:5 ../java/build/Proxy.java:11
msgid "Warning: Outproxy Not Found" msgid "Warning: Outproxy Not Found"
msgstr "" msgstr "Avertissement : outproxy non trouvé"
#: ../java/build/Proxy.java:6 ../java/build/Proxy.java:18 #: ../java/build/Proxy.java:6 ../java/build/Proxy.java:18
#: ../java/build/Proxy.java:27 ../java/build/Proxy.java:40 #: ../java/build/Proxy.java:27 ../java/build/Proxy.java:40
@ -85,6 +85,8 @@ msgid ""
"It is offline, there is network congestion, or your router is not yet well-" "It is offline, there is network congestion, or your router is not yet well-"
"integrated with peers." "integrated with peers."
msgstr "" msgstr ""
"Il est hors ligne, ou il ya congestion du réseau, ou votre routeur n'est pas "
"encore bien intégré avec les pairs."
#: ../java/build/Proxy.java:14 #: ../java/build/Proxy.java:14
#, java-format #, java-format
@ -92,6 +94,9 @@ msgid ""
"You may want to {0}retry{1} as this will randomly reselect an outproxy from " "You may want to {0}retry{1} as this will randomly reselect an outproxy from "
"the pool you have defined {2}here{3} (if you have more than one configured)." "the pool you have defined {2}here{3} (if you have more than one configured)."
msgstr "" msgstr ""
"Vous pouvez vouloir {0}réessayer{1} car cela va re-sélectionner au hasard un "
"outproxy du pool que vous avez défini {2}içi{3} (si vous en avez plus d'un "
"de configuré)."
#: ../java/build/Proxy.java:15 #: ../java/build/Proxy.java:15
#, java-format #, java-format
@ -99,6 +104,8 @@ msgid ""
"If you continue to have trouble you may want to edit your outproxy list {0}" "If you continue to have trouble you may want to edit your outproxy list {0}"
"here{1}." "here{1}."
msgstr "" msgstr ""
"Si vous continuez à avoir des dérangements vous pouvez vouloir modifier "
"votre liste de outproxy {0}içi{1}."
#: ../java/build/Proxy.java:16 ../java/build/Proxy.java:38 #: ../java/build/Proxy.java:16 ../java/build/Proxy.java:38
#: ../java/build/Proxy.java:59 ../java/build/Proxy.java:97 #: ../java/build/Proxy.java:59 ../java/build/Proxy.java:97
@ -107,11 +114,11 @@ msgstr "Destination du tunnel"
#: ../java/build/Proxy.java:17 #: ../java/build/Proxy.java:17
msgid "Error: Request Denied" msgid "Error: Request Denied"
msgstr "" msgstr "Erreur : demande refusée"
#: ../java/build/Proxy.java:23 #: ../java/build/Proxy.java:23
msgid "Error: Local Access" msgid "Error: Local Access"
msgstr "" msgstr "Erreur : accès local"
#: ../java/build/Proxy.java:24 #: ../java/build/Proxy.java:24
msgid "Your browser is misconfigured." msgid "Your browser is misconfigured."
@ -122,33 +129,39 @@ msgid ""
"Do not use the proxy to access the router console, localhost, or local LAN " "Do not use the proxy to access the router console, localhost, or local LAN "
"destinations." "destinations."
msgstr "" msgstr ""
"Ne pas utiliser le proxy pour accéder à la console du routeur, ni au "
"localhost, ni vers des destinations de votre LAN local."
#: ../java/build/Proxy.java:26 #: ../java/build/Proxy.java:26
msgid "Warning: Eepsite Unknown" msgid "Warning: Eepsite Unknown"
msgstr "" msgstr "Avertissement : Eepsite inconnu"
#: ../java/build/Proxy.java:32 #: ../java/build/Proxy.java:32
msgid "Warning: Eepsite Not Found in Addressbook" msgid "Warning: Eepsite Not Found in Addressbook"
msgstr "" msgstr "Avertissement : Eepsite pas trouvé dans le carnet d'adresses"
#: ../java/build/Proxy.java:33 #: ../java/build/Proxy.java:33
msgid "The eepsite was not found in your router's addressbook." msgid "The eepsite was not found in your router's addressbook."
msgstr "" msgstr ""
"Le eepsite n'a pas été trouvé dans le carnet d'adresses de votre routeur."
#: ../java/build/Proxy.java:34 #: ../java/build/Proxy.java:34
msgid "Check the link or find a Base 32 or Base 64 address." msgid "Check the link or find a Base 32 or Base 64 address."
msgstr "" msgstr "Cliquez le lien ou trouvez une adresse base 32 ou base 64."
#: ../java/build/Proxy.java:35 #: ../java/build/Proxy.java:35
#, java-format #, java-format
msgid "If you have the Base 64 address, {0}add it to your addressbook{1}." msgid "If you have the Base 64 address, {0}add it to your addressbook{1}."
msgstr "" msgstr ""
"Si vous avez l''adresse Base 64, {0}ajoutez-là à votre carnet d''adresse{1}."
#: ../java/build/Proxy.java:36 #: ../java/build/Proxy.java:36
msgid "" msgid ""
"Otherwise, find a Base 32 or address helper link, or use a jump service link " "Otherwise, find a Base 32 or address helper link, or use a jump service link "
"below." "below."
msgstr "" msgstr ""
"Sinon, trouver un lien d'assistant d'adresse ou un lien Base 32, ou utiliser "
"ci-dessous un lien service de saut."
#: ../java/build/Proxy.java:37 #: ../java/build/Proxy.java:37
#, java-format #, java-format
@ -156,83 +169,100 @@ msgid ""
"Seeing this page often? See {0}the FAQ{1} for help in {2}adding some " "Seeing this page often? See {0}the FAQ{1} for help in {2}adding some "
"subscriptions{3} to your addressbook." "subscriptions{3} to your addressbook."
msgstr "" msgstr ""
"Voyez-vous cette page souvent ? Voyez {0}la FAQ{1} pour de l'aide afin d'{2}"
"ajouter quelques abonnements{3} à votre carnet d'adresses."
#: ../java/build/Proxy.java:39 ../java/build/Proxy.java:45 #: ../java/build/Proxy.java:39 ../java/build/Proxy.java:45
msgid "Warning: Invalid Request URI" msgid "Warning: Invalid Request URI"
msgstr "" msgstr "Avertissement : demande invalide d'URI"
#: ../java/build/Proxy.java:46 #: ../java/build/Proxy.java:46
msgid "The request URI is invalid, and probably contains illegal characters." msgid "The request URI is invalid, and probably contains illegal characters."
msgstr "" msgstr ""
"L'URI de la requête n'est pas valide, et contient probablement des "
"caractères illégaux."
#: ../java/build/Proxy.java:47 #: ../java/build/Proxy.java:47
msgid "" msgid ""
"If you clicked a link, check the end of the URI for any characters the " "If you clicked a link, check the end of the URI for any characters the "
"browser has mistakenly added on." "browser has mistakenly added on."
msgstr "" msgstr ""
"Si vous avez cliqué sur un lien, vérifiez la fin de l'URI pour d'éventuels "
"caractères que le navigateur aurait ajourté à tort."
#: ../java/build/Proxy.java:48 ../java/build/Proxy.java:54 #: ../java/build/Proxy.java:48 ../java/build/Proxy.java:54
msgid "Warning: Invalid Destination" msgid "Warning: Invalid Destination"
msgstr "Destination locale" msgstr "Avertissement : destination invalide"
#: ../java/build/Proxy.java:55 #: ../java/build/Proxy.java:55
msgid "" msgid ""
"The eepsite destination specified was not valid, or was otherwise " "The eepsite destination specified was not valid, or was otherwise "
"unreachable." "unreachable."
msgstr "" msgstr ""
"La destination vers l'eepsite spécifié n'était pas valide, ou autrement "
"était inaccessible."
#: ../java/build/Proxy.java:56 #: ../java/build/Proxy.java:56
msgid "" msgid ""
"Perhaps you pasted in the wrong Base 64 string or the link you are following " "Perhaps you pasted in the wrong Base 64 string or the link you are following "
"is bad." "is bad."
msgstr "" msgstr ""
"Peut-être que vous avez collé dans la mauvaise chaîne base 64, ou le lien "
"que vous suivez est mauvais."
#: ../java/build/Proxy.java:57 #: ../java/build/Proxy.java:57
msgid "The I2P host could also be offline." msgid "The I2P host could also be offline."
msgstr "" msgstr "L'hôte I2P pourrait également être déconnecté."
#: ../java/build/Proxy.java:58 ../java/build/Proxy.java:96 #: ../java/build/Proxy.java:58 ../java/build/Proxy.java:96
#, java-format #, java-format
msgid "You may want to {0}retry{1}." msgid "You may want to {0}retry{1}."
msgstr "" msgstr "Vous pouvez vouloir {0}réessayer{1}."
#: ../java/build/Proxy.java:60 ../java/build/Proxy.java:66 #: ../java/build/Proxy.java:60 ../java/build/Proxy.java:66
msgid "Warning: Request Denied" msgid "Warning: Request Denied"
msgstr "" msgstr "Avertissement : demande refusée"
#: ../java/build/Proxy.java:67 #: ../java/build/Proxy.java:67
msgid "You attempted to connect to a non-I2P website or location." msgid "You attempted to connect to a non-I2P website or location."
msgstr "" msgstr "Vous avez tenté de vous connecter à un site ou emplacement non-I2P."
#: ../java/build/Proxy.java:68 ../java/build/Proxy.java:74 #: ../java/build/Proxy.java:68 ../java/build/Proxy.java:74
msgid "Warning: No Outproxy Configured" msgid "Warning: No Outproxy Configured"
msgstr "" msgstr "Avertissement : pas de outproxy configuré"
#: ../java/build/Proxy.java:75 #: ../java/build/Proxy.java:75
msgid "" msgid ""
"Your request was for a site outside of I2P, but you have no HTTP outproxy " "Your request was for a site outside of I2P, but you have no HTTP outproxy "
"configured." "configured."
msgstr "" msgstr ""
"Votre demande était pour un site en dehors de I2P, mais vous n'avez aucun "
"outproxy HTTP de configuré."
#: ../java/build/Proxy.java:76 #: ../java/build/Proxy.java:76
msgid "Please configure an outproxy in I2PTunnel." msgid "Please configure an outproxy in I2PTunnel."
msgstr "" msgstr "Veuillez configurer un outproxy dans I2PTunnel."
#: ../java/build/Proxy.java:77 ../java/build/Proxy.java:78 #: ../java/build/Proxy.java:77 ../java/build/Proxy.java:78
msgid "Warning: Destination Key Conflict" msgid "Warning: Destination Key Conflict"
msgstr "" msgstr "Avertissement : conflit de clé de destination"
#: ../java/build/Proxy.java:79 #: ../java/build/Proxy.java:79
msgid "" msgid ""
"The addresshelper link you followed specifies a different destination key " "The addresshelper link you followed specifies a different destination key "
"than a host entry in your host database." "than a host entry in your host database."
msgstr "" msgstr ""
"Le lien d'assistant d'adresse que vous avez suivi spécifie une clé de "
"destination différente de l'entrée d'hôte contenue dans votre base de "
"données hôte."
#: ../java/build/Proxy.java:80 #: ../java/build/Proxy.java:80
msgid "" msgid ""
"Someone could be trying to impersonate another eepsite, or people have given " "Someone could be trying to impersonate another eepsite, or people have given "
"two eepsites identical names." "two eepsites identical names."
msgstr "" msgstr ""
"Quelqu'un pourrait essayer de se faire passer pour un autre eepsite, ou des "
"gens ont donné des noms identiques à deux eepsites."
#: ../java/build/Proxy.java:81 #: ../java/build/Proxy.java:81
msgid "" msgid ""
@ -240,18 +270,24 @@ msgid ""
"discarding the addresshelper link, discarding the host entry from your host " "discarding the addresshelper link, discarding the host entry from your host "
"database, or naming one of them differently." "database, or naming one of them differently."
msgstr "" msgstr ""
"Vous pouvez résoudre le conflit en considérant à quelle clé vous faites "
"confiance, et soit rejeter le lien de l'assistant d'adresse en rejetant "
"l'entrée d'hôte hors de votre base de données hôte, ou nommer l'une d'elles "
"différemment."
#: ../java/build/Proxy.java:82 #: ../java/build/Proxy.java:82
msgid "Proxy Authorization Required" msgid "Proxy Authorization Required"
msgstr "Autorisation de mandataire sortant" msgstr "Autorisation de proxy requise"
#: ../java/build/Proxy.java:83 #: ../java/build/Proxy.java:83
msgid "I2P HTTP Proxy Authorization Required" msgid "I2P HTTP Proxy Authorization Required"
msgstr "Autorisation de mandataire sortant" msgstr "Autorisation de proxy HTTP I2P requise"
#: ../java/build/Proxy.java:84 #: ../java/build/Proxy.java:84
msgid "This proxy is configured to require a username and password for access." msgid "This proxy is configured to require a username and password for access."
msgstr "" msgstr ""
"Ce proxy est configuré pour exiger un nom d'utilisateur et un mot de passe "
"pour y accéder."
#: ../java/build/Proxy.java:85 #: ../java/build/Proxy.java:85
#, java-format #, java-format
@ -259,6 +295,8 @@ msgid ""
"Please enter your username and password, or check your {0}router " "Please enter your username and password, or check your {0}router "
"configuration{1} or {2}I2PTunnel configuration{3}." "configuration{1} or {2}I2PTunnel configuration{3}."
msgstr "" msgstr ""
"Veuillez saisir votre nom d''utilisateur et mot de passe, ou vérifier votre "
"{0}configuration de routeur{1} ou {2}configuration de I2PTunnel{3}."
#: ../java/build/Proxy.java:86 #: ../java/build/Proxy.java:86
#, java-format #, java-format
@ -266,93 +304,115 @@ msgid ""
"To disable authorization, remove the configuration {0}i2ptunnel.proxy." "To disable authorization, remove the configuration {0}i2ptunnel.proxy."
"auth=basic{1}, then stop and restart the HTTP Proxy tunnel." "auth=basic{1}, then stop and restart the HTTP Proxy tunnel."
msgstr "" msgstr ""
"Pour désactiver l''autorisation, supprimer la configuration {0}i2ptunnel."
"proxy.auth=basic{1}, puis arrêtez et redémarrez le tunnel du proxy HTTP."
#: ../java/build/Proxy.java:87 ../java/build/Proxy.java:93 #: ../java/build/Proxy.java:87 ../java/build/Proxy.java:93
msgid "Warning: Eepsite Unreachable" msgid "Warning: Eepsite Unreachable"
msgstr "" msgstr "Avertissement : Eepsite inaccessible"
#: ../java/build/Proxy.java:94 #: ../java/build/Proxy.java:94
msgid "The eepsite was not reachable." msgid "The eepsite was not reachable."
msgstr "" msgstr "Le eepsite n'était pas joignable."
#: ../java/build/Proxy.java:95 #: ../java/build/Proxy.java:95
msgid "" msgid ""
"The eepsite is offline, there is network congestion, or your router is not " "The eepsite is offline, there is network congestion, or your router is not "
"yet well-integrated with peers." "yet well-integrated with peers."
msgstr "" msgstr ""
"Le eepsite est hors ligne, ou il y a congestion du réseau, ou votre routeur "
"n'est pas encore bien intégré avec les pairs."
#: ../java/build/Proxy.java:98 #: ../java/build/Proxy.java:98
msgid "Information: New Host Name" msgid "Information: New Host Name"
msgstr "" msgstr "Information : nouveau nom d'hôte"
#: ../java/build/Proxy.java:104 #: ../java/build/Proxy.java:104
msgid "Information: New Host Name with Address Helper" msgid "Information: New Host Name with Address Helper"
msgstr "" msgstr "Information : nouveau nom d'hôte avec assistant d'adresse"
#: ../java/build/Proxy.java:105 #: ../java/build/Proxy.java:105
msgid "" msgid ""
"The address helper link you followed is for a new host name that is not in " "The address helper link you followed is for a new host name that is not in "
"your address book." "your address book."
msgstr "" msgstr ""
"Le lien d'assistant d'adresse que vous avez suivi est pour un nouveau nom "
"d'hôte qui n'est pas dans votre carnet d'adresses."
#: ../java/build/Proxy.java:106 #: ../java/build/Proxy.java:106
msgid "You may save this host name to your local address book." msgid "You may save this host name to your local address book."
msgstr "" msgstr ""
"Il vous est possible d'enregistrer ce nom d'hôte à votre carnet d'adresses "
"local."
#: ../java/build/Proxy.java:107 #: ../java/build/Proxy.java:107
msgid "" msgid ""
"If you save it to your address book, you will not see this message again." "If you save it to your address book, you will not see this message again."
msgstr "" msgstr ""
"Si vous l'enregistrez dans votre carnet d'adresses, vous ne verrez plus ce "
"message."
#: ../java/build/Proxy.java:108 #: ../java/build/Proxy.java:108
msgid "" msgid ""
"If you do not save it, the host name will be forgotten after the next router " "If you do not save it, the host name will be forgotten after the next router "
"restart." "restart."
msgstr "" msgstr ""
"Si vous n'enregistrez pas, le nom d'hôte sera oublié après le prochain "
"redémarrage du routeur."
#: ../java/build/Proxy.java:109 #: ../java/build/Proxy.java:109
msgid "" msgid ""
"If you do not wish to visit this host, click the \"back\" button on your " "If you do not wish to visit this host, click the \"back\" button on your "
"browser." "browser."
msgstr "" msgstr ""
"Si vous ne souhaitez pas visiter cet hôte, cliquez sur le bouton \"précédent"
"\" de votre navigateur."
#: ../java/build/Proxy.java:110 ../java/build/Proxy.java:116 #: ../java/build/Proxy.java:110 ../java/build/Proxy.java:116
msgid "Warning: Bad Address Helper" msgid "Warning: Bad Address Helper"
msgstr "" msgstr "Avertissement : mauvais assistant d'adresse"
#: ../java/build/Proxy.java:117 #: ../java/build/Proxy.java:117
#, java-format #, java-format
msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable." msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable."
msgstr "" msgstr ""
"La clé auxiliaire dans l''URL ({0}i2paddresshelper={1}) n''est pas résoluble."
#: ../java/build/Proxy.java:118 #: ../java/build/Proxy.java:118
msgid "It seems to be garbage data, or a mistyped Base 32 address." msgid "It seems to be garbage data, or a mistyped Base 32 address."
msgstr "" msgstr ""
"Il semble y avoir des données incorrectes, ou une faute de frappe dans "
"l'adresse Base 32."
#: ../java/build/Proxy.java:119 #: ../java/build/Proxy.java:119
msgid "" msgid ""
"Check your URL to try and fix the helper key to be a valid Base 32 hostname " "Check your URL to try and fix the helper key to be a valid Base 32 hostname "
"or Base 64 key." "or Base 64 key."
msgstr "" msgstr ""
"Vérifiez votre URL afin d'essayer de résoudre la clé d'assistance pour "
"qu'elle soit un nom d'hôte Base 32 valide ou clé Base 64."
#: ../java/build/Proxy.java:120 ../java/build/Proxy.java:126 #: ../java/build/Proxy.java:120 ../java/build/Proxy.java:126
msgid "Warning: Non-HTTP Protocol" msgid "Warning: Non-HTTP Protocol"
msgstr "" msgstr "Avertissement : protocole non HTTP"
#: ../java/build/Proxy.java:127 #: ../java/build/Proxy.java:127
msgid "The request uses a bad protocol." msgid "The request uses a bad protocol."
msgstr "" msgstr "La requête utilise un mauvais protocole."
#: ../java/build/Proxy.java:128 #: ../java/build/Proxy.java:128
#, java-format #, java-format
msgid "The I2P HTTP Proxy supports {0}http://{1} requests ONLY." msgid "The I2P HTTP Proxy supports {0}http://{1} requests ONLY."
msgstr "" msgstr ""
"Le proxy HTTP I2P prend en charge les demandes {0}http://{1} uniquement."
#: ../java/build/Proxy.java:129 #: ../java/build/Proxy.java:129
#, java-format #, java-format
msgid "" msgid ""
"Other protocols such as {0}https://{1} and {0}ftp://{1} are not allowed." "Other protocols such as {0}https://{1} and {0}ftp://{1} are not allowed."
msgstr "" msgstr ""
"D''autres protocoles tels que {0}https://{1} et {0}ftp://{1} ne sont pas "
"autorisés."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572
msgid "This seems to be a bad destination:" msgid "This seems to be a bad destination:"
@ -361,7 +421,8 @@ msgstr "Cela semble être une mauvaise destination"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572
msgid "i2paddresshelper cannot help you with a destination like that!" msgid "i2paddresshelper cannot help you with a destination like that!"
msgstr "" msgstr ""
"i2paddresshelper ne peut pas vous aider avec une destination comme cela !" "L'assistant d'adresse ne peut pas vous aider avec une destination comme "
"cela !"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:639 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:639
#, java-format #, java-format
@ -371,8 +432,8 @@ msgid ""
"\"{1}\">here</a>." "\"{1}\">here</a>."
msgstr "" msgstr ""
"Pour aller à la destination de votre base de données d''hôtes, cliquez <a " "Pour aller à la destination de votre base de données d''hôtes, cliquez <a "
"href=\"{0}\">here</a>. Pour aller à la destination de l''aide d''adresse en " "href=\"{0}\">içi</a>. Pour aller à la destination de l''assistant d''adresse "
"conflit, cliquez <a href=\"{1}\">ici</a>." "en conflit, cliquez <a href=\"{1}\">içi</a>."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1043 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1043
msgid "Host" msgid "Host"

View File

@ -4,20 +4,18 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers # To contribute translations, see http://www.i2p2.de/newdevelopers
# #
# Translators: # Translators:
# sfix <anon-9b36b2e@lycos.com>, 2013 # Андрей Лукьяненко <operru32@yandex.ru>, 2013
# ducki2p <ducki2p@gmail.com>, 2011 # ducki2p <ducki2p@gmail.com>, 2011
# foo <foo@bar>, 2009 # foo <foo@bar>, 2009
# gmind <grvmind@gmail.com>, 2012-2013 # gmind, 2012-2013
# gmind <grvmind@gmail.com>, 2013
# gmind <grvmind@gmail.com>, 2012
# sfix <anon-9b36b2e@lycos.com>, 2013 # sfix <anon-9b36b2e@lycos.com>, 2013
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P i2ptunnel\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-11 14:28+0000\n" "POT-Creation-Date: 2013-09-20 10:17+0000\n"
"PO-Revision-Date: 2013-07-05 08:09+0000\n" "PO-Revision-Date: 2013-09-14 22:04+0000\n"
"Last-Translator: Roman Azarenko <x12ozmouse@ya.ru>\n" "Last-Translator: Андрей Лукьяненко <operru32@yandex.ru>\n"
"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/I2P/" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/I2P/"
"language/ru_RU/)\n" "language/ru_RU/)\n"
"Language: ru_RU\n" "Language: ru_RU\n"
@ -29,7 +27,7 @@ msgstr ""
#: ../java/build/Proxy.java:5 ../java/build/Proxy.java:11 #: ../java/build/Proxy.java:5 ../java/build/Proxy.java:11
msgid "Warning: Outproxy Not Found" msgid "Warning: Outproxy Not Found"
msgstr "" msgstr "Предупреждение: Выходной прокси-сервер недоступен"
#: ../java/build/Proxy.java:6 ../java/build/Proxy.java:18 #: ../java/build/Proxy.java:6 ../java/build/Proxy.java:18
#: ../java/build/Proxy.java:27 ../java/build/Proxy.java:40 #: ../java/build/Proxy.java:27 ../java/build/Proxy.java:40
@ -89,6 +87,8 @@ msgid ""
"It is offline, there is network congestion, or your router is not yet well-" "It is offline, there is network congestion, or your router is not yet well-"
"integrated with peers." "integrated with peers."
msgstr "" msgstr ""
"Возможно, он отключен, сеть перегружена или ваш маршрутизатор недостаточно "
"интегрирован с другими узлами."
#: ../java/build/Proxy.java:14 #: ../java/build/Proxy.java:14
#, java-format #, java-format
@ -96,6 +96,9 @@ msgid ""
"You may want to {0}retry{1} as this will randomly reselect an outproxy from " "You may want to {0}retry{1} as this will randomly reselect an outproxy from "
"the pool you have defined {2}here{3} (if you have more than one configured)." "the pool you have defined {2}here{3} (if you have more than one configured)."
msgstr "" msgstr ""
"Вы можете {0}повторить{1} операцию (это случайным образом выберет прокси-"
"сервер из определенного {2}здесь{3} списка, если вы настроили более одного "
"прокси-сервера)."
#: ../java/build/Proxy.java:15 #: ../java/build/Proxy.java:15
#, java-format #, java-format
@ -103,6 +106,8 @@ msgid ""
"If you continue to have trouble you may want to edit your outproxy list {0}" "If you continue to have trouble you may want to edit your outproxy list {0}"
"here{1}." "here{1}."
msgstr "" msgstr ""
"Если проблема продолжит появляться, вы можете изменить список прокси-"
"серверов {0}здесь{1}."
#: ../java/build/Proxy.java:16 ../java/build/Proxy.java:38 #: ../java/build/Proxy.java:16 ../java/build/Proxy.java:38
#: ../java/build/Proxy.java:59 ../java/build/Proxy.java:97 #: ../java/build/Proxy.java:59 ../java/build/Proxy.java:97
@ -111,11 +116,11 @@ msgstr "Назначение туннеля"
#: ../java/build/Proxy.java:17 #: ../java/build/Proxy.java:17
msgid "Error: Request Denied" msgid "Error: Request Denied"
msgstr "" msgstr "Ошибка: Отказ в выполнении запроса"
#: ../java/build/Proxy.java:23 #: ../java/build/Proxy.java:23
msgid "Error: Local Access" msgid "Error: Local Access"
msgstr "" msgstr "Ошибка: Локальный адрес"
#: ../java/build/Proxy.java:24 #: ../java/build/Proxy.java:24
msgid "Your browser is misconfigured." msgid "Your browser is misconfigured."
@ -126,33 +131,37 @@ msgid ""
"Do not use the proxy to access the router console, localhost, or local LAN " "Do not use the proxy to access the router console, localhost, or local LAN "
"destinations." "destinations."
msgstr "" msgstr ""
"Не используйте прокси-сервер для доступа к консоли маршрутизатора, "
"локальному компьютеру или локальной сети."
#: ../java/build/Proxy.java:26 #: ../java/build/Proxy.java:26
msgid "Warning: Eepsite Unknown" msgid "Warning: Eepsite Unknown"
msgstr "" msgstr "Предупреждение: Неизвестный сайт I2P"
#: ../java/build/Proxy.java:32 #: ../java/build/Proxy.java:32
msgid "Warning: Eepsite Not Found in Addressbook" msgid "Warning: Eepsite Not Found in Addressbook"
msgstr "" msgstr "Предупреждение: Сайт I2P не найден в адресной книге"
#: ../java/build/Proxy.java:33 #: ../java/build/Proxy.java:33
msgid "The eepsite was not found in your router's addressbook." msgid "The eepsite was not found in your router's addressbook."
msgstr "" msgstr "Сайт I2P не найден в адресной книге вашего маршрутизатора."
#: ../java/build/Proxy.java:34 #: ../java/build/Proxy.java:34
msgid "Check the link or find a Base 32 or Base 64 address." msgid "Check the link or find a Base 32 or Base 64 address."
msgstr "" msgstr "Проверьте ссылку или найдите адрес Base32 или Base64."
#: ../java/build/Proxy.java:35 #: ../java/build/Proxy.java:35
#, java-format #, java-format
msgid "If you have the Base 64 address, {0}add it to your addressbook{1}." msgid "If you have the Base 64 address, {0}add it to your addressbook{1}."
msgstr "" msgstr "Если у вас есть адрес Base64, {0}добавьте его в адресную книгу{1}."
#: ../java/build/Proxy.java:36 #: ../java/build/Proxy.java:36
msgid "" msgid ""
"Otherwise, find a Base 32 or address helper link, or use a jump service link " "Otherwise, find a Base 32 or address helper link, or use a jump service link "
"below." "below."
msgstr "" msgstr ""
"В противном случае найдите ссылку Base32 или AddressHelper или используйте "
"Jump-службу."
#: ../java/build/Proxy.java:37 #: ../java/build/Proxy.java:37
#, java-format #, java-format
@ -160,20 +169,24 @@ msgid ""
"Seeing this page often? See {0}the FAQ{1} for help in {2}adding some " "Seeing this page often? See {0}the FAQ{1} for help in {2}adding some "
"subscriptions{3} to your addressbook." "subscriptions{3} to your addressbook."
msgstr "" msgstr ""
"Если вы слишком часто попадаете на эту страницу, то обратитесь к {0}FAQ{1} "
"за инструкциями по {2}добавлению подписок{3} адресной книги."
#: ../java/build/Proxy.java:39 ../java/build/Proxy.java:45 #: ../java/build/Proxy.java:39 ../java/build/Proxy.java:45
msgid "Warning: Invalid Request URI" msgid "Warning: Invalid Request URI"
msgstr "" msgstr "Предупреждение: Некорректный URI запроса"
#: ../java/build/Proxy.java:46 #: ../java/build/Proxy.java:46
msgid "The request URI is invalid, and probably contains illegal characters." msgid "The request URI is invalid, and probably contains illegal characters."
msgstr "" msgstr "Некорректный URI запроса. Возможно, он содержит недопустимые символы."
#: ../java/build/Proxy.java:47 #: ../java/build/Proxy.java:47
msgid "" msgid ""
"If you clicked a link, check the end of the URI for any characters the " "If you clicked a link, check the end of the URI for any characters the "
"browser has mistakenly added on." "browser has mistakenly added on."
msgstr "" msgstr ""
"Если вы прошли по ссылке, проверьте конец URI на наличие символов, ошибочно "
"добавленных браузером."
#: ../java/build/Proxy.java:48 ../java/build/Proxy.java:54 #: ../java/build/Proxy.java:48 ../java/build/Proxy.java:54
msgid "Warning: Invalid Destination" msgid "Warning: Invalid Destination"
@ -183,60 +196,68 @@ msgstr "Локальный адрес назначения"
msgid "" msgid ""
"The eepsite destination specified was not valid, or was otherwise " "The eepsite destination specified was not valid, or was otherwise "
"unreachable." "unreachable."
msgstr "" msgstr "Указанный адрес недействителен или недоступен."
#: ../java/build/Proxy.java:56 #: ../java/build/Proxy.java:56
msgid "" msgid ""
"Perhaps you pasted in the wrong Base 64 string or the link you are following " "Perhaps you pasted in the wrong Base 64 string or the link you are following "
"is bad." "is bad."
msgstr "" msgstr ""
"Возможно, вы вставили неправильную строку Base64 или прошли по нерабочей "
"ссылке."
#: ../java/build/Proxy.java:57 #: ../java/build/Proxy.java:57
msgid "The I2P host could also be offline." msgid "The I2P host could also be offline."
msgstr "" msgstr "Сайт I2P также может быть отключен."
#: ../java/build/Proxy.java:58 ../java/build/Proxy.java:96 #: ../java/build/Proxy.java:58 ../java/build/Proxy.java:96
#, java-format #, java-format
msgid "You may want to {0}retry{1}." msgid "You may want to {0}retry{1}."
msgstr "" msgstr "Вы можете {0}повторить{1} операцию."
#: ../java/build/Proxy.java:60 ../java/build/Proxy.java:66 #: ../java/build/Proxy.java:60 ../java/build/Proxy.java:66
msgid "Warning: Request Denied" msgid "Warning: Request Denied"
msgstr "" msgstr "Предупреждение: Отказ в выполнении запроса"
#: ../java/build/Proxy.java:67 #: ../java/build/Proxy.java:67
msgid "You attempted to connect to a non-I2P website or location." msgid "You attempted to connect to a non-I2P website or location."
msgstr "" msgstr "Вы попытались соединиться с сайтом не в сети I2P."
#: ../java/build/Proxy.java:68 ../java/build/Proxy.java:74 #: ../java/build/Proxy.java:68 ../java/build/Proxy.java:74
msgid "Warning: No Outproxy Configured" msgid "Warning: No Outproxy Configured"
msgstr "" msgstr "Предупреждение: Выходной прокси-сервер не настроен"
#: ../java/build/Proxy.java:75 #: ../java/build/Proxy.java:75
msgid "" msgid ""
"Your request was for a site outside of I2P, but you have no HTTP outproxy " "Your request was for a site outside of I2P, but you have no HTTP outproxy "
"configured." "configured."
msgstr "" msgstr ""
"Вы запросили страницу вне сети I2P, но не имеете настроенного выходного "
"прокси-сервера."
#: ../java/build/Proxy.java:76 #: ../java/build/Proxy.java:76
msgid "Please configure an outproxy in I2PTunnel." msgid "Please configure an outproxy in I2PTunnel."
msgstr "" msgstr "Пожалуйста, настройте выходной прокси-сервер в I2PTunnel."
#: ../java/build/Proxy.java:77 ../java/build/Proxy.java:78 #: ../java/build/Proxy.java:77 ../java/build/Proxy.java:78
msgid "Warning: Destination Key Conflict" msgid "Warning: Destination Key Conflict"
msgstr "" msgstr "Предупреждение: Конфликт ключа назначения"
#: ../java/build/Proxy.java:79 #: ../java/build/Proxy.java:79
msgid "" msgid ""
"The addresshelper link you followed specifies a different destination key " "The addresshelper link you followed specifies a different destination key "
"than a host entry in your host database." "than a host entry in your host database."
msgstr "" msgstr ""
"Ссылка AddressHelper, по которой вы прошли, определяет ключ назначения, "
"отличный от указанного в адресной книге."
#: ../java/build/Proxy.java:80 #: ../java/build/Proxy.java:80
msgid "" msgid ""
"Someone could be trying to impersonate another eepsite, or people have given " "Someone could be trying to impersonate another eepsite, or people have given "
"two eepsites identical names." "two eepsites identical names."
msgstr "" msgstr ""
"Кто-то может пытаться выдать себя за другой сайт или разные люди дали двум "
"сайтам одинаковые имена."
#: ../java/build/Proxy.java:81 #: ../java/build/Proxy.java:81
msgid "" msgid ""
@ -244,6 +265,9 @@ msgid ""
"discarding the addresshelper link, discarding the host entry from your host " "discarding the addresshelper link, discarding the host entry from your host "
"database, or naming one of them differently." "database, or naming one of them differently."
msgstr "" msgstr ""
"Для разрешения конфликта вы можете определить, какому ключу вы доверяете, и "
"либо отказаться от прохода по ссылке, либо удалить старый ключ, либо "
"присвоить одному из них другое имя."
#: ../java/build/Proxy.java:82 #: ../java/build/Proxy.java:82
msgid "Proxy Authorization Required" msgid "Proxy Authorization Required"
@ -255,7 +279,7 @@ msgstr "Авторизация outproxy"
#: ../java/build/Proxy.java:84 #: ../java/build/Proxy.java:84
msgid "This proxy is configured to require a username and password for access." msgid "This proxy is configured to require a username and password for access."
msgstr "" msgstr "Этот прокси-сервер требует имя пользователя и пароль для доступа."
#: ../java/build/Proxy.java:85 #: ../java/build/Proxy.java:85
#, java-format #, java-format
@ -263,6 +287,8 @@ msgid ""
"Please enter your username and password, or check your {0}router " "Please enter your username and password, or check your {0}router "
"configuration{1} or {2}I2PTunnel configuration{3}." "configuration{1} or {2}I2PTunnel configuration{3}."
msgstr "" msgstr ""
"Введите имя и пароль или проверьте ваши {0}настройки маршрутизатора{1} и {2}"
"настройки I2PTunnel{3}."
#: ../java/build/Proxy.java:86 #: ../java/build/Proxy.java:86
#, java-format #, java-format
@ -270,93 +296,106 @@ msgid ""
"To disable authorization, remove the configuration {0}i2ptunnel.proxy." "To disable authorization, remove the configuration {0}i2ptunnel.proxy."
"auth=basic{1}, then stop and restart the HTTP Proxy tunnel." "auth=basic{1}, then stop and restart the HTTP Proxy tunnel."
msgstr "" msgstr ""
"Для отключения авторизации удалите строку {0}i2ptunnel.proxy.auth=basic{1} и "
"перезапустите туннель HTTP Proxy."
#: ../java/build/Proxy.java:87 ../java/build/Proxy.java:93 #: ../java/build/Proxy.java:87 ../java/build/Proxy.java:93
msgid "Warning: Eepsite Unreachable" msgid "Warning: Eepsite Unreachable"
msgstr "" msgstr "Предупреждение: Сайт I2P недоступен"
#: ../java/build/Proxy.java:94 #: ../java/build/Proxy.java:94
msgid "The eepsite was not reachable." msgid "The eepsite was not reachable."
msgstr "" msgstr "Сайт I2P недоступен."
#: ../java/build/Proxy.java:95 #: ../java/build/Proxy.java:95
msgid "" msgid ""
"The eepsite is offline, there is network congestion, or your router is not " "The eepsite is offline, there is network congestion, or your router is not "
"yet well-integrated with peers." "yet well-integrated with peers."
msgstr "" msgstr ""
"Возможно, он отключен, сеть перегружена или ваш маршрутизатор недостаточно "
"интегрирован с другими узлами."
#: ../java/build/Proxy.java:98 #: ../java/build/Proxy.java:98
msgid "Information: New Host Name" msgid "Information: New Host Name"
msgstr "" msgstr "Информация: Новый доменной адрес"
#: ../java/build/Proxy.java:104 #: ../java/build/Proxy.java:104
msgid "Information: New Host Name with Address Helper" msgid "Information: New Host Name with Address Helper"
msgstr "" msgstr "Информация: Новый доменной адрес с AddressHelper"
#: ../java/build/Proxy.java:105 #: ../java/build/Proxy.java:105
msgid "" msgid ""
"The address helper link you followed is for a new host name that is not in " "The address helper link you followed is for a new host name that is not in "
"your address book." "your address book."
msgstr "" msgstr ""
"Ссылка AddressHelper, по которой вы прошли, ведет на домен, не внесенный в "
"адресную книгу."
#: ../java/build/Proxy.java:106 #: ../java/build/Proxy.java:106
msgid "You may save this host name to your local address book." msgid "You may save this host name to your local address book."
msgstr "" msgstr "Вы можете сохранить этот домен в свою локальную адресную книгу."
#: ../java/build/Proxy.java:107 #: ../java/build/Proxy.java:107
msgid "" msgid ""
"If you save it to your address book, you will not see this message again." "If you save it to your address book, you will not see this message again."
msgstr "" msgstr ""
"Если вы сохраните его в вашей адресной книге, вы больше не будете видеть это "
"сообщение."
#: ../java/build/Proxy.java:108 #: ../java/build/Proxy.java:108
msgid "" msgid ""
"If you do not save it, the host name will be forgotten after the next router " "If you do not save it, the host name will be forgotten after the next router "
"restart." "restart."
msgstr "" msgstr ""
"Если вы не сохраните его, он будет «забыт» после перезапуска маршрутизатора."
#: ../java/build/Proxy.java:109 #: ../java/build/Proxy.java:109
msgid "" msgid ""
"If you do not wish to visit this host, click the \"back\" button on your " "If you do not wish to visit this host, click the \"back\" button on your "
"browser." "browser."
msgstr "" msgstr ""
"Если вы не хотите посещать этот сайт, нажмите кнопку «Назад» в браузере."
#: ../java/build/Proxy.java:110 ../java/build/Proxy.java:116 #: ../java/build/Proxy.java:110 ../java/build/Proxy.java:116
msgid "Warning: Bad Address Helper" msgid "Warning: Bad Address Helper"
msgstr "" msgstr "Предупреждение: Некорректный AddressHelper"
#: ../java/build/Proxy.java:117 #: ../java/build/Proxy.java:117
#, java-format #, java-format
msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable." msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable."
msgstr "" msgstr "Не удается разобрать ключ AddressHelper ({0}i2paddresshelper={1})."
#: ../java/build/Proxy.java:118 #: ../java/build/Proxy.java:118
msgid "It seems to be garbage data, or a mistyped Base 32 address." msgid "It seems to be garbage data, or a mistyped Base 32 address."
msgstr "" msgstr "Возможно, он содержит ненужные данные или опечатку в адресе Base32."
#: ../java/build/Proxy.java:119 #: ../java/build/Proxy.java:119
msgid "" msgid ""
"Check your URL to try and fix the helper key to be a valid Base 32 hostname " "Check your URL to try and fix the helper key to be a valid Base 32 hostname "
"or Base 64 key." "or Base 64 key."
msgstr "" msgstr ""
"Проверьте URL и попробуйте исправить ссылку с использованием корректной "
"ссылки Base32 или Base64."
#: ../java/build/Proxy.java:120 ../java/build/Proxy.java:126 #: ../java/build/Proxy.java:120 ../java/build/Proxy.java:126
msgid "Warning: Non-HTTP Protocol" msgid "Warning: Non-HTTP Protocol"
msgstr "" msgstr "Предупреждение: Протокол не HTTP"
#: ../java/build/Proxy.java:127 #: ../java/build/Proxy.java:127
msgid "The request uses a bad protocol." msgid "The request uses a bad protocol."
msgstr "" msgstr "Запрос отправлен через неподдерживанмый протокол."
#: ../java/build/Proxy.java:128 #: ../java/build/Proxy.java:128
#, java-format #, java-format
msgid "The I2P HTTP Proxy supports {0}http://{1} requests ONLY." msgid "The I2P HTTP Proxy supports {0}http://{1} requests ONLY."
msgstr "" msgstr "HTTP-прокси I2P поддерживает ТОЛЬКО протокол {0}http://{1}."
#: ../java/build/Proxy.java:129 #: ../java/build/Proxy.java:129
#, java-format #, java-format
msgid "" msgid ""
"Other protocols such as {0}https://{1} and {0}ftp://{1} are not allowed." "Other protocols such as {0}https://{1} and {0}ftp://{1} are not allowed."
msgstr "" msgstr ""
"Другие протоколы, такие как {0}https://{1} и {0}ftp://{1} не поддерживаются."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572
msgid "This seems to be a bad destination:" msgid "This seems to be a bad destination:"

View File

@ -4,15 +4,14 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers # To contribute translations, see http://www.i2p2.de/newdevelopers
# #
# Translators: # Translators:
# <i2p@robertfoss.se>, 2013. # hottuna <i2p@robertfoss.se>, 2013
# <i2p@robertfoss.se>, 2012. # hottuna <i2p@robertfoss.se>, 2012
# Martin Svensson <digitalmannen@gmail.com>, 2011-2012.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P i2ptunnel\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-07-13 18:50+0000\n" "POT-Creation-Date: 2013-09-26 21:42+0000\n"
"PO-Revision-Date: 2013-01-19 16:53+0000\n" "PO-Revision-Date: 2013-09-26 06:34+0000\n"
"Last-Translator: hottuna <i2p@robertfoss.se>\n" "Last-Translator: hottuna <i2p@robertfoss.se>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/" "Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/"
"language/sv_SE/)\n" "language/sv_SE/)\n"
@ -22,336 +21,382 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../java/build/Proxy.java:5 #: ../java/build/Proxy.java:5 ../java/build/Proxy.java:11
msgid "Proxy Authorization Required" msgid "Warning: Outproxy Not Found"
msgstr "Tillstånd för utproxy" msgstr "Varning: Utproxy Ej Hittad"
#: ../java/build/Proxy.java:6 #: ../java/build/Proxy.java:6 ../java/build/Proxy.java:18
msgid "I2P HTTP Proxy Authorization Required" #: ../java/build/Proxy.java:27 ../java/build/Proxy.java:40
msgstr "Tillstånd för utproxy" #: ../java/build/Proxy.java:49 ../java/build/Proxy.java:61
#: ../java/build/Proxy.java:69 ../java/build/Proxy.java:88
#: ../java/build/Proxy.java:7 #: ../java/build/Proxy.java:99 ../java/build/Proxy.java:111
msgid "This proxy is configured to require a username and password for access." #: ../java/build/Proxy.java:121
msgstr ""
#: ../java/build/Proxy.java:8
#, java-format
msgid ""
"Please enter your username and password, or check your {0}router "
"configuration{1} or {2}I2PTunnel configuration{3}."
msgstr ""
#: ../java/build/Proxy.java:9
#, java-format
msgid ""
"To disable authorization, remove the configuration {0}i2ptunnel.proxy."
"auth=basic{1}, then stop and restart the HTTP Proxy tunnel."
msgstr ""
#: ../java/build/Proxy.java:10 ../java/build/Proxy.java:16
msgid "Warning: No Outproxy Configured"
msgstr ""
#: ../java/build/Proxy.java:11 ../java/build/Proxy.java:20
#: ../java/build/Proxy.java:32 ../java/build/Proxy.java:44
#: ../java/build/Proxy.java:52 ../java/build/Proxy.java:61
#: ../java/build/Proxy.java:74 ../java/build/Proxy.java:83
#: ../java/build/Proxy.java:93 ../java/build/Proxy.java:103
#: ../java/build/Proxy.java:115
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:196 #: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:196
msgid "Router Console" msgid "Router Console"
msgstr "Router konsol " msgstr "Routerkonsol"
#: ../java/build/Proxy.java:12 ../java/build/Proxy.java:21 #: ../java/build/Proxy.java:7 ../java/build/Proxy.java:19
#: ../java/build/Proxy.java:33 ../java/build/Proxy.java:45 #: ../java/build/Proxy.java:28 ../java/build/Proxy.java:41
#: ../java/build/Proxy.java:53 ../java/build/Proxy.java:62 #: ../java/build/Proxy.java:50 ../java/build/Proxy.java:62
#: ../java/build/Proxy.java:75 ../java/build/Proxy.java:84 #: ../java/build/Proxy.java:70 ../java/build/Proxy.java:89
#: ../java/build/Proxy.java:94 ../java/build/Proxy.java:104 #: ../java/build/Proxy.java:100 ../java/build/Proxy.java:112
#: ../java/build/Proxy.java:116 #: ../java/build/Proxy.java:122
msgid "I2P Router Console" msgid "I2P Router Console"
msgstr "Router konsol " msgstr "Routerkonsol"
#: ../java/build/Proxy.java:13 ../java/build/Proxy.java:22 #: ../java/build/Proxy.java:8 ../java/build/Proxy.java:20
#: ../java/build/Proxy.java:34 ../java/build/Proxy.java:46 #: ../java/build/Proxy.java:29 ../java/build/Proxy.java:42
#: ../java/build/Proxy.java:54 ../java/build/Proxy.java:63 #: ../java/build/Proxy.java:51 ../java/build/Proxy.java:63
#: ../java/build/Proxy.java:76 ../java/build/Proxy.java:85 #: ../java/build/Proxy.java:71 ../java/build/Proxy.java:90
#: ../java/build/Proxy.java:95 ../java/build/Proxy.java:105 #: ../java/build/Proxy.java:101 ../java/build/Proxy.java:113
#: ../java/build/Proxy.java:117 #: ../java/build/Proxy.java:123
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197 #: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Configuration" msgid "Configuration"
msgstr "Konfiguration" msgstr "Konfiguration"
#: ../java/build/Proxy.java:14 ../java/build/Proxy.java:23 #: ../java/build/Proxy.java:9 ../java/build/Proxy.java:21
#: ../java/build/Proxy.java:35 ../java/build/Proxy.java:47 #: ../java/build/Proxy.java:30 ../java/build/Proxy.java:43
#: ../java/build/Proxy.java:55 ../java/build/Proxy.java:64 #: ../java/build/Proxy.java:52 ../java/build/Proxy.java:64
#: ../java/build/Proxy.java:77 ../java/build/Proxy.java:86 #: ../java/build/Proxy.java:72 ../java/build/Proxy.java:91
#: ../java/build/Proxy.java:96 ../java/build/Proxy.java:106 #: ../java/build/Proxy.java:102 ../java/build/Proxy.java:114
#: ../java/build/Proxy.java:118 #: ../java/build/Proxy.java:124
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197 #: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Help" msgid "Help"
msgstr "Hjälp" msgstr "Hjälp"
#: ../java/build/Proxy.java:15 ../java/build/Proxy.java:24 #: ../java/build/Proxy.java:10 ../java/build/Proxy.java:22
#: ../java/build/Proxy.java:36 ../java/build/Proxy.java:48 #: ../java/build/Proxy.java:31 ../java/build/Proxy.java:44
#: ../java/build/Proxy.java:56 ../java/build/Proxy.java:65 #: ../java/build/Proxy.java:53 ../java/build/Proxy.java:65
#: ../java/build/Proxy.java:78 ../java/build/Proxy.java:87 #: ../java/build/Proxy.java:73 ../java/build/Proxy.java:92
#: ../java/build/Proxy.java:97 ../java/build/Proxy.java:107 #: ../java/build/Proxy.java:103 ../java/build/Proxy.java:115
#: ../java/build/Proxy.java:119 #: ../java/build/Proxy.java:125
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197 #: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Addressbook" msgid "Addressbook"
msgstr "Adressbok" msgstr "Adressbok"
#: ../java/build/Proxy.java:17 #: ../java/build/Proxy.java:12
msgid ""
"Your request was for a site outside of I2P, but you have no HTTP outproxy "
"configured."
msgstr ""
#: ../java/build/Proxy.java:18
msgid "Please configure an outproxy in I2PTunnel."
msgstr ""
#: ../java/build/Proxy.java:19
msgid "Information: New Host Name"
msgstr ""
#: ../java/build/Proxy.java:25
msgid "Information: New Host Name with Address Helper"
msgstr ""
#: ../java/build/Proxy.java:26
msgid ""
"The address helper link you followed is for a new host name that is not in "
"your address book."
msgstr ""
#: ../java/build/Proxy.java:27
msgid "You may save this host name to your local address book."
msgstr ""
#: ../java/build/Proxy.java:28
msgid ""
"If you save it to your address book, you will not see this message again."
msgstr ""
#: ../java/build/Proxy.java:29
msgid ""
"If you do not save it, the host name will be forgotten after the next router "
"restart."
msgstr ""
#: ../java/build/Proxy.java:30
msgid ""
"If you do not wish to visit this host, click the \"back\" button on your "
"browser."
msgstr ""
#: ../java/build/Proxy.java:31 ../java/build/Proxy.java:37
msgid "Warning: Invalid Destination"
msgstr "Lokalt mål"
#: ../java/build/Proxy.java:38
msgid ""
"The eepsite destination specified was not valid, or was otherwise "
"unreachable."
msgstr ""
#: ../java/build/Proxy.java:39
msgid ""
"Perhaps you pasted in the wrong Base 64 string or the link you are following "
"is bad."
msgstr ""
#: ../java/build/Proxy.java:40
msgid "The I2P host could also be offline."
msgstr ""
#: ../java/build/Proxy.java:41 ../java/build/Proxy.java:123
#, java-format
msgid "You may want to {0}retry{1}."
msgstr ""
#: ../java/build/Proxy.java:42 ../java/build/Proxy.java:72
#: ../java/build/Proxy.java:113 ../java/build/Proxy.java:124
msgid "Could not find the following destination:"
msgstr "Mål för tunnel"
#: ../java/build/Proxy.java:43 ../java/build/Proxy.java:49
msgid "Warning: Request Denied"
msgstr ""
#: ../java/build/Proxy.java:50
msgid "You attempted to connect to a non-I2P website or location."
msgstr ""
#: ../java/build/Proxy.java:51 ../java/build/Proxy.java:57
msgid "Warning: Invalid Request URI"
msgstr ""
#: ../java/build/Proxy.java:58
msgid "The request URI is invalid, and probably contains illegal characters."
msgstr ""
#: ../java/build/Proxy.java:59
msgid ""
"If you clicked a link, check the end of the URI for any characters the "
"browser has mistakenly added on."
msgstr ""
#: ../java/build/Proxy.java:60
msgid "Warning: Eepsite Unknown"
msgstr ""
#: ../java/build/Proxy.java:66
msgid "Warning: Eepsite Not Found in Addressbook"
msgstr ""
#: ../java/build/Proxy.java:67
msgid "The eepsite was not found in your router's addressbook."
msgstr ""
#: ../java/build/Proxy.java:68
msgid "Check the link or find a Base 32 or Base 64 address."
msgstr ""
#: ../java/build/Proxy.java:69
#, java-format
msgid "If you have the Base 64 address, {0}add it to your addressbook{1}."
msgstr ""
#: ../java/build/Proxy.java:70
msgid ""
"Otherwise, find a Base 32 or address helper link, or use a jump service link "
"below."
msgstr ""
#: ../java/build/Proxy.java:71
#, java-format
msgid ""
"Seeing this page often? See {0}the FAQ{1} for help in {2}adding some "
"subscriptions{3} to your addressbook."
msgstr ""
#: ../java/build/Proxy.java:73
msgid "Error: Request Denied"
msgstr ""
#: ../java/build/Proxy.java:79
msgid "Error: Local Access"
msgstr ""
#: ../java/build/Proxy.java:80
msgid "Your browser is misconfigured."
msgstr "Din webbläsare stödjer inte iFrames."
#: ../java/build/Proxy.java:81
msgid ""
"Do not use the proxy to access the router console, localhost, or local LAN "
"destinations."
msgstr ""
#: ../java/build/Proxy.java:82 ../java/build/Proxy.java:88
msgid "Warning: Non-HTTP Protocol"
msgstr ""
#: ../java/build/Proxy.java:89
msgid "The request uses a bad protocol."
msgstr ""
#: ../java/build/Proxy.java:90
#, java-format
msgid "The I2P HTTP Proxy supports {0}http://{1} requests ONLY."
msgstr ""
#: ../java/build/Proxy.java:91
#, java-format
msgid ""
"Other protocols such as {0}https://{1} and {0}ftp://{1} are not allowed."
msgstr ""
#: ../java/build/Proxy.java:92 ../java/build/Proxy.java:98
msgid "Warning: Bad Address Helper"
msgstr ""
#: ../java/build/Proxy.java:99
#, java-format
msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable."
msgstr ""
#: ../java/build/Proxy.java:100
msgid "It seems to be garbage data, or a mistyped Base 32 address."
msgstr ""
#: ../java/build/Proxy.java:101
msgid ""
"Check your URL to try and fix the helper key to be a valid Base 32 hostname "
"or Base 64 key."
msgstr ""
#: ../java/build/Proxy.java:102 ../java/build/Proxy.java:108
msgid "Warning: Outproxy Not Found"
msgstr ""
#: ../java/build/Proxy.java:109
msgid "The HTTP Outproxy was not found." msgid "The HTTP Outproxy was not found."
msgstr "HTTP proxyn är inte uppe" msgstr "HTTP Utproxyn hittades ej."
#: ../java/build/Proxy.java:110 #: ../java/build/Proxy.java:13
msgid "" msgid ""
"It is offline, there is network congestion, or your router is not yet well-" "It is offline, there is network congestion, or your router is not yet well-"
"integrated with peers." "integrated with peers."
msgstr "" msgstr ""
"Den är antingen offline, nätverket är under stor belastning eller så är din "
"router ännu inte väl integrerad med peers."
#: ../java/build/Proxy.java:111 #: ../java/build/Proxy.java:14
#, java-format #, java-format
msgid "" msgid ""
"You may want to {0}retry{1} as this will randomly reselect an outproxy from " "You may want to {0}retry{1} as this will randomly reselect an outproxy from "
"the pool you have defined {2}here{3} (if you have more than one configured)." "the pool you have defined {2}here{3} (if you have more than one configured)."
msgstr "" msgstr ""
"Du kanske vill {0}försöka igen{1} eftersom en ny utproxy kommer väljas "
"slumpmässigt utav de som är definierade {2}här{3} (om du har mer än en "
"inställd)."
#: ../java/build/Proxy.java:112 #: ../java/build/Proxy.java:15
#, java-format #, java-format
msgid "" msgid ""
"If you continue to have trouble you may want to edit your outproxy list {0}" "If you continue to have trouble you may want to edit your outproxy list {0}"
"here{1}." "here{1}."
msgstr "" msgstr ""
"Om du fortsätter att ha problem, så kanske du vill ändra din utproxy-liste "
"{0}här{1}."
#: ../java/build/Proxy.java:114 ../java/build/Proxy.java:120 #: ../java/build/Proxy.java:16 ../java/build/Proxy.java:38
msgid "Warning: Eepsite Unreachable" #: ../java/build/Proxy.java:59 ../java/build/Proxy.java:97
msgstr "" msgid "Could not find the following destination:"
msgstr "Kunde inte hitta följande mål:"
#: ../java/build/Proxy.java:121 #: ../java/build/Proxy.java:17
msgid "The eepsite was not reachable." msgid "Error: Request Denied"
msgstr "" msgstr "Fel: Förfrågan Nekad"
#: ../java/build/Proxy.java:122 #: ../java/build/Proxy.java:23
msgid "Error: Local Access"
msgstr "Fel: Lokal Åtkomst"
#: ../java/build/Proxy.java:24
msgid "Your browser is misconfigured."
msgstr "Din webbläsare är felkonfigurerad."
#: ../java/build/Proxy.java:25
msgid "" msgid ""
"The eepsite is offline, there is network congestion, or your router is not " "Do not use the proxy to access the router console, localhost, or local LAN "
"yet well-integrated with peers." "destinations."
msgstr "" msgstr ""
"Använd inte proxyn för åtkomst till routerkonsolen, localhost eller lokala "
"LAN mål."
#: ../java/build/Proxy.java:125 ../java/build/Proxy.java:126 #: ../java/build/Proxy.java:26
msgid "Warning: Eepsite Unknown"
msgstr "Varning: Okänd Eepsite"
#: ../java/build/Proxy.java:32
msgid "Warning: Eepsite Not Found in Addressbook"
msgstr "Varning: Eepsite Finns Inte i Adressboken"
#: ../java/build/Proxy.java:33
msgid "The eepsite was not found in your router's addressbook."
msgstr "Eepsite:n hittades inte i din routers adressbok."
#: ../java/build/Proxy.java:34
msgid "Check the link or find a Base 32 or Base 64 address."
msgstr "Kontrollera länken eller hitta en Base32 eller Base64 adress."
#: ../java/build/Proxy.java:35
#, java-format
msgid "If you have the Base 64 address, {0}add it to your addressbook{1}."
msgstr "Om du har en Base64-adress, {0}lägg till den till din adressbok{1}."
#: ../java/build/Proxy.java:36
msgid ""
"Otherwise, find a Base 32 or address helper link, or use a jump service link "
"below."
msgstr ""
"Annars, hitta en Base32 eller adresshjälpar-länk eller använder en hopp-"
"tjänst länk nedan."
#: ../java/build/Proxy.java:37
#, java-format
msgid ""
"Seeing this page often? See {0}the FAQ{1} for help in {2}adding some "
"subscriptions{3} to your addressbook."
msgstr ""
"Ser du denhär sidan ofta? Kika i {0}FAQ:en{1} efter hjälp med att {2}lägga "
"till några prenumerationer{3} till din adressbok."
#: ../java/build/Proxy.java:39 ../java/build/Proxy.java:45
msgid "Warning: Invalid Request URI"
msgstr "Varning: Ogiltig URI Begärd"
#: ../java/build/Proxy.java:46
msgid "The request URI is invalid, and probably contains illegal characters."
msgstr ""
"Den begärde URI:n är ogiltig och innehåller troligtvis ogiltiga tecken."
#: ../java/build/Proxy.java:47
msgid ""
"If you clicked a link, check the end of the URI for any characters the "
"browser has mistakenly added on."
msgstr ""
"Om du klicka på en länk, kontrollera slutet av URI:n efter andra tecken som "
"webbläsaren av misstag lagt till."
#: ../java/build/Proxy.java:48 ../java/build/Proxy.java:54
msgid "Warning: Invalid Destination"
msgstr "Varning: Ogiltigt Mål"
#: ../java/build/Proxy.java:55
msgid ""
"The eepsite destination specified was not valid, or was otherwise "
"unreachable."
msgstr ""
"Eepsite målet som specificerades är inte giltigt eller kan annars ej nås."
#: ../java/build/Proxy.java:56
msgid ""
"Perhaps you pasted in the wrong Base 64 string or the link you are following "
"is bad."
msgstr ""
"Kanske kopierade du in fel Base64 sträng eller så är länken du följer dålig."
#: ../java/build/Proxy.java:57
msgid "The I2P host could also be offline."
msgstr "I2P-värden kan också vara offline."
#: ../java/build/Proxy.java:58 ../java/build/Proxy.java:96
#, java-format
msgid "You may want to {0}retry{1}."
msgstr "Du kanske vill {0}försöka igen{1}."
#: ../java/build/Proxy.java:60 ../java/build/Proxy.java:66
msgid "Warning: Request Denied"
msgstr "Varning: Förfrågan Nekad"
#: ../java/build/Proxy.java:67
msgid "You attempted to connect to a non-I2P website or location."
msgstr "Du försökte ansluta till en icke-I2P webbsida eller plats."
#: ../java/build/Proxy.java:68 ../java/build/Proxy.java:74
msgid "Warning: No Outproxy Configured"
msgstr "Varning: Ingen Utproxy Inställd"
#: ../java/build/Proxy.java:75
msgid ""
"Your request was for a site outside of I2P, but you have no HTTP outproxy "
"configured."
msgstr ""
"Din förfrågan var för en sida utanför I2P, men du har ingen HTTP utproxy "
"inställd."
#: ../java/build/Proxy.java:76
msgid "Please configure an outproxy in I2PTunnel."
msgstr "Var god ställ in en utproxy i I2PTunnel."
#: ../java/build/Proxy.java:77 ../java/build/Proxy.java:78
msgid "Warning: Destination Key Conflict" msgid "Warning: Destination Key Conflict"
msgstr "" msgstr "Varning: Konflikt för Mål-nyckeln"
#: ../java/build/Proxy.java:127 #: ../java/build/Proxy.java:79
msgid "" msgid ""
"The addresshelper link you followed specifies a different destination key " "The addresshelper link you followed specifies a different destination key "
"than a host entry in your host database." "than a host entry in your host database."
msgstr "" msgstr ""
"Adresshjälpar-länken du följde specifierad en annan mål-nyckel än för den "
"värd som finns i din värd-databas."
#: ../java/build/Proxy.java:128 #: ../java/build/Proxy.java:80
msgid "" msgid ""
"Someone could be trying to impersonate another eepsite, or people have given " "Someone could be trying to impersonate another eepsite, or people have given "
"two eepsites identical names." "two eepsites identical names."
msgstr "" msgstr ""
"Någon kanske försöker utge sig för att vara en annan eepsite eller personer "
"kan ha givit eepsites identiska namn."
#: ../java/build/Proxy.java:129 #: ../java/build/Proxy.java:81
msgid "" msgid ""
"You can resolve the conflict by considering which key you trust, and either " "You can resolve the conflict by considering which key you trust, and either "
"discarding the addresshelper link, discarding the host entry from your host " "discarding the addresshelper link, discarding the host entry from your host "
"database, or naming one of them differently." "database, or naming one of them differently."
msgstr "" msgstr ""
"Du kan lösa konflikten genom att överväga vilken nyckel du litar på och "
"antingen kasta bort adresshjälpar-länken, kasta bort värdnamnet från din "
"värd-databas eller namnge dom olikt."
#: ../java/build/Proxy.java:82
msgid "Proxy Authorization Required"
msgstr "Proxy Tillstånd Krävs"
#: ../java/build/Proxy.java:83
msgid "I2P HTTP Proxy Authorization Required"
msgstr "I2P HTTP Proxy Tillstånd Krävs"
#: ../java/build/Proxy.java:84
msgid "This proxy is configured to require a username and password for access."
msgstr ""
"Denhär proxy är inställd till att kräva användarnamn och lösenord för "
"åtkomst."
#: ../java/build/Proxy.java:85
#, java-format
msgid ""
"Please enter your username and password, or check your {0}router "
"configuration{1} or {2}I2PTunnel configuration{3}."
msgstr ""
"Var god ange ditt användarnamn och lösenord eller kontrollera din {0}router-"
"konfiguration{1} eller {2}I2PTunnel-konfiguration{3}."
#: ../java/build/Proxy.java:86
#, java-format
msgid ""
"To disable authorization, remove the configuration {0}i2ptunnel.proxy."
"auth=basic{1}, then stop and restart the HTTP Proxy tunnel."
msgstr ""
"För att slå av autentisering, ta bort inställningen {0}i2ptunnel.proxy."
"auth=basic{1}, stanna och starta sedan om HTTP Porxy tunneln."
#: ../java/build/Proxy.java:87 ../java/build/Proxy.java:93
msgid "Warning: Eepsite Unreachable"
msgstr "Varning: Eepsite Kan Ej Nås"
#: ../java/build/Proxy.java:94
msgid "The eepsite was not reachable."
msgstr "Eepsiten var inte nåbar."
#: ../java/build/Proxy.java:95
msgid ""
"The eepsite is offline, there is network congestion, or your router is not "
"yet well-integrated with peers."
msgstr ""
"Eepsiten är offline, nätverket är uner hög belastning eller din router är "
"ännu inte väl integrerad med peers."
#: ../java/build/Proxy.java:98
msgid "Information: New Host Name"
msgstr "Information: Nytt Värdnamn"
#: ../java/build/Proxy.java:104
msgid "Information: New Host Name with Address Helper"
msgstr "Information: Nytt Värdnamn med Adresshjälpare"
#: ../java/build/Proxy.java:105
msgid ""
"The address helper link you followed is for a new host name that is not in "
"your address book."
msgstr ""
"Adressjälpar-länken du följde är för ett nytt värdnamn som inte är i din "
"adressbok."
#: ../java/build/Proxy.java:106
msgid "You may save this host name to your local address book."
msgstr "Du kan spara detta värdnamn i din lokala adressbok."
#: ../java/build/Proxy.java:107
msgid ""
"If you save it to your address book, you will not see this message again."
msgstr ""
"Om du sparar det i din adressbok, så kommer du inte se dethär meddelandet "
"igen."
#: ../java/build/Proxy.java:108
msgid ""
"If you do not save it, the host name will be forgotten after the next router "
"restart."
msgstr ""
"Om du inte sparar det, så kommer värdnamnet glömmas bort efter nästa router-"
"omstart."
#: ../java/build/Proxy.java:109
msgid ""
"If you do not wish to visit this host, click the \"back\" button on your "
"browser."
msgstr ""
"Om du inte vill besöka värden, klicka på \"tillbaka\"-knappen i din "
"webbläsare."
#: ../java/build/Proxy.java:110 ../java/build/Proxy.java:116
msgid "Warning: Bad Address Helper"
msgstr "Varning: Dålig Adresshjälpare"
#: ../java/build/Proxy.java:117
#, java-format
msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable."
msgstr ""
"Hjälpar-nyckeln i URL:en ({0}i2paddresshelper={1}) är inte möjlig att hitta."
#: ../java/build/Proxy.java:118
msgid "It seems to be garbage data, or a mistyped Base 32 address."
msgstr "Det verkar vara skräp-data eller en felskriven Base32 adress."
#: ../java/build/Proxy.java:119
msgid ""
"Check your URL to try and fix the helper key to be a valid Base 32 hostname "
"or Base 64 key."
msgstr ""
"Kontrollera din URL för att försöka fixa hjälpar-nyckeln så att den är ett "
"giltigt Base32 värdnamn eller Base64 nyckel."
#: ../java/build/Proxy.java:120 ../java/build/Proxy.java:126
msgid "Warning: Non-HTTP Protocol"
msgstr "Varning: Ej HTTP Protokoll"
#: ../java/build/Proxy.java:127
msgid "The request uses a bad protocol."
msgstr "Förfrågan använder ett dåligt protokoll."
#: ../java/build/Proxy.java:128
#, java-format
msgid "The I2P HTTP Proxy supports {0}http://{1} requests ONLY."
msgstr "I2P HTTP Proxyn stödjer ENBART {0}http://{1} frågor."
#: ../java/build/Proxy.java:129
#, java-format
msgid ""
"Other protocols such as {0}https://{1} and {0}ftp://{1} are not allowed."
msgstr "Andra protokoll som {0}https://{1} och {0}ftp://{1} är inte tillåtna."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572
msgid "This seems to be a bad destination:" msgid "This seems to be a bad destination:"
@ -409,7 +454,7 @@ msgstr "Spara {0} till privatadressbok och fortsätt till eepsite "
msgid "HTTP Outproxy" msgid "HTTP Outproxy"
msgstr "HTTP Utproxy" msgstr "HTTP Utproxy"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1185 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1216
msgid "" msgid ""
"Click a link below to look for an address helper by using a \"jump\" service:" "Click a link below to look for an address helper by using a \"jump\" service:"
msgstr "" msgstr ""
@ -417,7 +462,7 @@ msgstr ""
"en \"hopp\" tjänst" "en \"hopp\" tjänst"
#. Translators: parameter is a host name #. Translators: parameter is a host name
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1221 #: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1224
#, java-format #, java-format
msgid "{0} jump service" msgid "{0} jump service"
msgstr "{0} hopptjänst" msgstr "{0} hopptjänst"

View File

@ -6,20 +6,21 @@
# Translators: # Translators:
# blabla, 2011 # blabla, 2011
# blabla <blabla@trash-mail.com>, 2011-2012 # blabla <blabla@trash-mail.com>, 2011-2012
# D.A. Loader <>, 2012 # D.A. Loader, 2012
# driz <driz@i2pmail.org>, 2012 # driz <driz@i2pmail.org>, 2012
# ducki2p <ducki2p@gmail.com>, 2011 # ducki2p <ducki2p@gmail.com>, 2011
# foo <foo@bar>, 2009 # foo <foo@bar>, 2009
# mixxy, 2011 # mixxy, 2011
# nextloop <ga25day@mytum.de>, 2013
# pirr <pirr@tormail.org>, 2012 # pirr <pirr@tormail.org>, 2012
# zeroflag <zeroflag@i2pmail.org>, 2013 # zeroflag <zeroflag@i2pmail.org>, 2013
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-07-02 17:24+0000\n" "POT-Creation-Date: 2013-09-26 21:33+0000\n"
"PO-Revision-Date: 2013-05-08 13:15+0000\n" "PO-Revision-Date: 2013-09-23 22:32+0000\n"
"Last-Translator: zeroflag <zeroflag@i2pmail.org>\n" "Last-Translator: nextloop <ga25day@mytum.de>\n"
"Language-Team: German (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: German (http://www.transifex.com/projects/p/I2P/language/"
"de/)\n" "de/)\n"
"Language: de\n" "Language: de\n"
@ -28,126 +29,6 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572
msgid "This seems to be a bad destination:"
msgstr "Dies scheint kein gültiges Ziel zu sein:"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:572
msgid "i2paddresshelper cannot help you with a destination like that!"
msgstr "Der I2P-Adresshelfer kann dir bei solch einem Ziel nicht helfen."
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:639
#, java-format
msgid ""
"To visit the destination in your host database, click <a href=\"{0}\">here</"
"a>. To visit the conflicting addresshelper destination, click <a href="
"\"{1}\">here</a>."
msgstr ""
"Um das Ziel in Ihrer Host-Datenbank zu besuchen, klicken Sie <a href="
"\"{0}\">hier</a>, und um das Ziel aus der kollidierenden Adresshelfer-"
"Anfrage zu besuchen, <a href=\"{1}\">hier</a>!"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1043
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:385
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:159
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:389
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:410
msgid "Host"
msgstr "Host"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1047
msgid "Base 32"
msgstr "Base 32"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1051
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:377
msgid "Destination"
msgstr "Ziel"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1057
#, java-format
msgid "Continue to {0} without saving"
msgstr "Weiter zu {0}, ohne zu speichern"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1062
#, java-format
msgid "Save {0} to router address book and continue to eepsite"
msgstr "{0} im Router-Adressbuch speichern und auf die Eepseite weiterleiten"
#. only blockfile supports multiple books
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1065
#, java-format
msgid "Save {0} to master address book and continue to eepsite"
msgstr "{0} im Master-Adressbuch speichern und auf die Eepseite weiterleiten"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1066
#, java-format
msgid "Save {0} to private address book and continue to eepsite"
msgstr "{0} im privaten Adressbuch speichern und auf die Eepseite weiterleiten"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1180
msgid "HTTP Outproxy"
msgstr "HTTP-Outproxy"
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1185
msgid ""
"Click a link below to look for an address helper by using a \"jump\" service:"
msgstr ""
"Durch Klicken auf einen der untenstehenden Links bekommen Sie einen "
"Adresshelfer von einem \"Sprung\"-Service:"
#. Translators: parameter is a host name
#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1221
#, java-format
msgid "{0} jump service"
msgstr "Weiterleitungsdienst {0}"
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:163
#, java-format
msgid "Added via address helper from {0}"
msgstr "Hinzugefüg über den Adressenhelfer von {0}"
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:165
msgid "Added via address helper"
msgstr "Durch Adresshelfer hinzugefügt"
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:190
#, java-format
msgid "Redirecting to {0}"
msgstr "Weiterleitung zu {0}"
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:196
msgid "Router Console"
msgstr "Routerkonsole"
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Addressbook"
msgstr "Adressbuch"
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Configuration"
msgstr "Einstellungen"
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:197
msgid "Help"
msgstr "Hilfe"
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:202
#, java-format
msgid "Saved {0} to the {1} addressbook, redirecting now."
msgstr ""
"{0} wurde ins {1} Adressbuch geschrieben. Du wirst nun weitergeleitet."
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:203
#, java-format
msgid "Failed to save {0} to the {1} addressbook, redirecting now."
msgstr ""
"Konnte {0} nicht im {1} Adressbuch speichern. Du wirst nun weitergeleitet."
#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:205
msgid "Click here if you are not redirected automatically."
msgstr "Klick hier, wenn du nicht automatisch weitergeleitet wirst!"
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:325 #: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:325
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:335 #: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:335
msgid "internal" msgid "internal"
@ -162,17 +43,15 @@ msgstr[1] ""
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:408 #: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:408
msgid "lower bandwidth and reliability" msgid "lower bandwidth and reliability"
msgstr "" msgstr "niedrigere Bandbreite und Zuverlässlichkeit"
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:410 #: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:410
#, fuzzy
msgid "standard bandwidth and reliability" msgid "standard bandwidth and reliability"
msgstr "" msgstr "standard Bandbreite und Zuverlässlichkeit"
"2 eingehende, 2 ausgehende Tunnel (Standardbandbreitennutzung, zuverlässig)"
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:412 #: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:412
msgid "higher bandwidth and reliability" msgid "higher bandwidth and reliability"
msgstr "" msgstr "hohe Bandbreite und Zuverlässlichkeit"
#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:119 #: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:119
msgid "Tunnels are not initialized yet, please reload in two minutes." msgid "Tunnels are not initialized yet, please reload in two minutes."
@ -563,6 +442,13 @@ msgstr "für Verbindungen mit Anfragen/Antworten"
msgid "Router I2CP Address" msgid "Router I2CP Address"
msgstr "I2CP-Adresse des Routers" msgstr "I2CP-Adresse des Routers"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:385
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:159
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:389
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:410
msgid "Host"
msgstr "Host"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:393 #: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:393
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:165 #: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:165
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:397 #: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:397
@ -932,6 +818,10 @@ msgstr "Wartestellung"
msgid "Outproxy" msgid "Outproxy"
msgstr "Ausgehender Proxy" msgstr "Ausgehender Proxy"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:377
msgid "Destination"
msgstr "Ziel"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:397 #: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:397
msgid "none" msgid "none"
msgstr "Keiner" msgstr "Keiner"
@ -1350,26 +1240,3 @@ msgstr "Abschließen"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:724 #: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:724
msgid "Next" msgid "Next"
msgstr "Nächstes" msgstr "Nächstes"
#~ msgid ""
#~ "1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)"
#~ msgstr ""
#~ "1 eingehender, 1 ausgehender Tunnel (geringe Bandbreitennutzung, weniger "
#~ "zuverlässig)"
#~ msgid ""
#~ "3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)"
#~ msgstr ""
#~ "3 eingehende, 3 ausgehende Tunnel (hohe Bandbreitennutzung, zuverlässiger)"
#~ msgid "tunnels"
#~ msgstr "Tunnel"
#~ msgid "4 in, 4 out (high traffic server)"
#~ msgstr "4 eingehend, 4 ausgehend (Server mit großem Datenverkehr)"
#~ msgid "5 in, 5 out (high traffic server)"
#~ msgstr "5 eingehend, 5 ausgehend (Server mit großem Datenverkehr)"
#~ msgid "6 in, 6 out (high traffic server)"
#~ msgstr "6 eingehend, 6 ausgehend (Server mit großem Datenverkehr)"

View File

@ -13,8 +13,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-11 14:30+0000\n" "POT-Creation-Date: 2013-09-20 10:24+0000\n"
"PO-Revision-Date: 2013-07-16 15:35+0000\n" "PO-Revision-Date: 2013-08-13 14:14+0000\n"
"Last-Translator: Boxoa590\n" "Last-Translator: Boxoa590\n"
"Language-Team: French (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: French (http://www.transifex.com/projects/p/I2P/language/"
"fr/)\n" "fr/)\n"
@ -33,8 +33,8 @@ msgstr "interne"
#, java-format #, java-format
msgid "{0} inbound, {0} outbound tunnel" msgid "{0} inbound, {0} outbound tunnel"
msgid_plural "{0} inbound, {0} outbound tunnels" msgid_plural "{0} inbound, {0} outbound tunnels"
msgstr[0] "" msgstr[0] "{0} entrant, {0} sortant tunnels"
msgstr[1] "" msgstr[1] "{0} entrants, {0} sortants tunnels"
#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:408 #: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:408
msgid "lower bandwidth and reliability" msgid "lower bandwidth and reliability"
@ -1247,79 +1247,3 @@ msgstr "Terminer"
#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:724 #: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:724
msgid "Next" msgid "Next"
msgstr "Suivant" msgstr "Suivant"
#~ msgid "This seems to be a bad destination:"
#~ msgstr "Cela semble être une mauvaise destination"
#~ msgid "i2paddresshelper cannot help you with a destination like that!"
#~ msgstr ""
#~ "i2paddresshelper ne peut pas vous aider avec une destination comme cela !"
#~ msgid ""
#~ "To visit the destination in your host database, click <a href="
#~ "\"{0}\">here</a>. To visit the conflicting addresshelper destination, "
#~ "click <a href=\"{1}\">here</a>."
#~ msgstr ""
#~ "Pour aller à la destination de votre base de données d''hôtes, cliquez <a "
#~ "href=\"{0}\">here</a>. Pour aller à la destination de l''aide d''adresse "
#~ "en conflit, cliquez <a href=\"{1}\">ici</a>."
#~ msgid "Base 32"
#~ msgstr "Base 32"
#~ msgid "Continue to {0} without saving"
#~ msgstr ""
#~ "Aller sur le site i2p {0} sans enregistrer dans un carnet d'adresses. "
#~ msgid "Save {0} to router address book and continue to eepsite"
#~ msgstr ""
#~ "Ajouter au carnet d''adresse du routeur {0} et aller sur le site i2p"
#~ msgid "Save {0} to master address book and continue to eepsite"
#~ msgstr "Ajouter au carnet d''adresse principal {0} et aller sur le site i2p"
#~ msgid "Save {0} to private address book and continue to eepsite"
#~ msgstr "Ajouter au carnet d''adresse privé {0} et aller sur le site i2p"
#~ msgid "HTTP Outproxy"
#~ msgstr "proxy sortant HTTP"
#~ msgid ""
#~ "Click a link below to look for an address helper by using a \"jump\" "
#~ "service:"
#~ msgstr ""
#~ "Cliquez sur un des liens ci-dessous pour chercher une aide d'adresse en "
#~ "utilisant un \"service de saut\":"
#~ msgid "{0} jump service"
#~ msgstr "{0} jump service"
#~ msgid "Added via address helper from {0}"
#~ msgstr "Ajouté via assistant d''adresse depuis {0}"
#~ msgid "Added via address helper"
#~ msgstr "Ajouté via assitant d'adresse"
#~ msgid "Redirecting to {0}"
#~ msgstr "Redirection vers {0}"
#~ msgid "Router Console"
#~ msgstr "Console du routeur"
#~ msgid "Addressbook"
#~ msgstr "Carnet d'adresses"
#~ msgid "Configuration"
#~ msgstr "Configuration"
#~ msgid "Help"
#~ msgstr "Aide"
#~ msgid "Saved {0} to the {1} addressbook, redirecting now."
#~ msgstr "{0} ajouté au carnet d''adresses {1}. Redirection en cours."
#~ msgid "Failed to save {0} to the {1} addressbook, redirecting now."
#~ msgstr "{0} non ajouté au carnet d''adresses {1}. Redirection en cours."
#~ msgid "Click here if you are not redirected automatically."
#~ msgstr "Cliquez ici si vous n'êtes pas redirigé automatiquement."

File diff suppressed because it is too large Load Diff

View File

@ -121,6 +121,7 @@
<!-- Update the messages_*.po files. <!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true --> We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" /> <arg value="./bundle-messages.sh" />
</exec> </exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >
@ -167,6 +168,7 @@
<target name="bundle-news" unless="no.bundle"> <target name="bundle-news" unless="no.bundle">
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages-news.sh" /> <arg value="./bundle-messages-news.sh" />
</exec> </exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >

View File

@ -15,6 +15,10 @@ TMPFILE=build/javafiles-news.txt
export TZ=UTC export TZ=UTC
RC=0 RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ] if [ "$1" = "-p" ]
then then
POUPDATE=1 POUPDATE=1

View File

@ -15,6 +15,10 @@ TMPFILE=build/javafiles.txt
export TZ=UTC export TZ=UTC
RC=0 RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ] if [ "$1" = "-p" ]
then then
POUPDATE=1 POUPDATE=1

View File

@ -19,6 +19,7 @@ import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.crypto.SU3File;
import net.i2p.crypto.TrustedUpdate; import net.i2p.crypto.TrustedUpdate;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.router.Router; import net.i2p.router.Router;
@ -69,6 +70,7 @@ public class ConsoleUpdateManager implements UpdateManager {
private final Map<UpdateItem, Version> _downloaded; private final Map<UpdateItem, Version> _downloaded;
/** downloaded AND installed */ /** downloaded AND installed */
private final Map<UpdateItem, Version> _installed; private final Map<UpdateItem, Version> _installed;
private final boolean _allowTorrent;
private static final DecimalFormat _pct = new DecimalFormat("0.0%"); private static final DecimalFormat _pct = new DecimalFormat("0.0%");
private volatile String _status; private volatile String _status;
@ -90,6 +92,13 @@ public class ConsoleUpdateManager implements UpdateManager {
_downloaded = new ConcurrentHashMap(); _downloaded = new ConcurrentHashMap();
_installed = new ConcurrentHashMap(); _installed = new ConcurrentHashMap();
_status = ""; _status = "";
// DEBUG slow start for snark updates
// For 0.9.4 update, only for dev builds
// For 0.9.5 update, only for dev builds and 1% more
// For 0.9.6 update, only for dev builds and 3% more
// For 0.9.8 update, only for dev builds and 30% more
// Remove this for 100%
_allowTorrent = RouterVersion.BUILD != 0 || _context.random().nextInt(100) < 30;
} }
public static ConsoleUpdateManager getInstance() { public static ConsoleUpdateManager getInstance() {
@ -99,6 +108,7 @@ public class ConsoleUpdateManager implements UpdateManager {
public void start() { public void start() {
notifyInstalled(NEWS, "", Long.toString(NewsHelper.lastUpdated(_context))); notifyInstalled(NEWS, "", Long.toString(NewsHelper.lastUpdated(_context)));
notifyInstalled(ROUTER_SIGNED, "", RouterVersion.VERSION); notifyInstalled(ROUTER_SIGNED, "", RouterVersion.VERSION);
notifyInstalled(ROUTER_SIGNED_SU3, "", RouterVersion.VERSION);
// hack to init from the current news file... do this before we register Updaters // hack to init from the current news file... do this before we register Updaters
// This will not kick off any Updaters as none are yet registered // This will not kick off any Updaters as none are yet registered
(new NewsFetcher(_context, this, Collections.EMPTY_LIST)).checkForUpdates(); (new NewsFetcher(_context, this, Collections.EMPTY_LIST)).checkForUpdates();
@ -122,6 +132,15 @@ public class ConsoleUpdateManager implements UpdateManager {
register(c, ROUTER_SIGNED, HTTP, 0); // news is an update checker for the router register(c, ROUTER_SIGNED, HTTP, 0); // news is an update checker for the router
Updater u = new UpdateHandler(_context, this); Updater u = new UpdateHandler(_context, this);
register(u, ROUTER_SIGNED, HTTP, 0); register(u, ROUTER_SIGNED, HTTP, 0);
if (ConfigUpdateHandler.USE_SU3_UPDATE) {
register(c, ROUTER_SIGNED_SU3, HTTP, 0);
register(u, ROUTER_SIGNED_SU3, HTTP, 0);
// todo
//register(c, ROUTER_SIGNED_SU3, HTTPS_CLEARNET, 0);
//register(u, ROUTER_SIGNED_SU3, HTTPS_CLEARNET, -10);
//register(c, ROUTER_SIGNED_SU3, HTTP_CLEARNET, 0);
//register(u, ROUTER_SIGNED_SU3, HTTP_CLEARNET, -20);
}
// TODO see NewsFetcher // TODO see NewsFetcher
//register(u, ROUTER_SIGNED, HTTPS_CLEARNET, -5); //register(u, ROUTER_SIGNED, HTTPS_CLEARNET, -5);
//register(u, ROUTER_SIGNED, HTTP_CLEARNET, -10); //register(u, ROUTER_SIGNED, HTTP_CLEARNET, -10);
@ -560,18 +579,18 @@ public class ConsoleUpdateManager implements UpdateManager {
* Call once for each type/method pair. * Call once for each type/method pair.
*/ */
public void register(Updater updater, UpdateType type, UpdateMethod method, int priority) { public void register(Updater updater, UpdateType type, UpdateMethod method, int priority) {
if ((type == ROUTER_SIGNED || type == ROUTER_UNSIGNED) && NewsHelper.dontInstall(_context)) { if ((type == ROUTER_SIGNED || type == ROUTER_UNSIGNED || type == ROUTER_SIGNED_SU3) &&
NewsHelper.dontInstall(_context)) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Ignoring registration for " + type + ", router updates disabled"); _log.warn("Ignoring registration for " + type + ", router updates disabled");
return; return;
} }
// DEBUG slow start for snark updates if (type == ROUTER_SIGNED_SU3 && !ConfigUpdateHandler.USE_SU3_UPDATE) {
// For 0.9.4 update, only for dev builds if (_log.shouldLog(Log.WARN))
// For 0.9.5 update, only for dev builds and 1% more _log.warn("Ignoring registration for " + type + ", SU3 updates disabled");
// For 0.9.6 update, only for dev builds and 3% more return;
// For 0.9.8 update, only for dev builds and 30% more }
// Remove this for 100% if (method == TORRENT && !_allowTorrent) {
if (method == TORRENT && RouterVersion.BUILD == 0 && _context.random().nextInt(100) > 29) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Ignoring torrent registration"); _log.warn("Ignoring torrent registration");
return; return;
@ -725,8 +744,10 @@ public class ConsoleUpdateManager implements UpdateManager {
// fall through // fall through
case ROUTER_SIGNED: case ROUTER_SIGNED:
case ROUTER_SIGNED_SU3:
if (shouldInstall() && if (shouldInstall() &&
!(isUpdateInProgress(ROUTER_SIGNED) || !(isUpdateInProgress(ROUTER_SIGNED) ||
isUpdateInProgress(ROUTER_SIGNED_SU3) ||
isUpdateInProgress(ROUTER_UNSIGNED))) { isUpdateInProgress(ROUTER_UNSIGNED))) {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Updating " + ui + " after notify"); _log.info("Updating " + ui + " after notify");
@ -810,6 +831,7 @@ public class ConsoleUpdateManager implements UpdateManager {
switch (task.getType()) { switch (task.getType()) {
case NEWS: case NEWS:
case ROUTER_SIGNED: case ROUTER_SIGNED:
case ROUTER_SIGNED_SU3:
case ROUTER_UNSIGNED: case ROUTER_UNSIGNED:
// ConfigUpdateHandler, SummaryHelper, SummaryBarRenderer handle status display // ConfigUpdateHandler, SummaryHelper, SummaryBarRenderer handle status display
break; break;
@ -926,6 +948,12 @@ public class ConsoleUpdateManager implements UpdateManager {
notifyDownloaded(task.getType(), task.getID(), actualVersion); notifyDownloaded(task.getType(), task.getID(), actualVersion);
break; break;
case ROUTER_SIGNED_SU3:
rv = handleSu3File(task.getURI(), actualVersion, file);
if (rv)
notifyDownloaded(task.getType(), task.getID(), actualVersion);
break;
case ROUTER_UNSIGNED: case ROUTER_UNSIGNED:
rv = handleUnsignedFile(task.getURI(), actualVersion, file); rv = handleUnsignedFile(task.getURI(), actualVersion, file);
if (rv) { if (rv) {
@ -981,10 +1009,30 @@ public class ConsoleUpdateManager implements UpdateManager {
_log.info(ui + " " + ver + " downloaded"); _log.info(ui + " " + ver + " downloaded");
_downloaded.put(ui, ver); _downloaded.put(ui, ver);
// one trumps the other // one trumps the other
if (type == ROUTER_SIGNED) if (type == ROUTER_SIGNED) {
_downloaded.remove(new UpdateItem(ROUTER_UNSIGNED, "")); _downloaded.remove(new UpdateItem(ROUTER_UNSIGNED, ""));
else if (type == ROUTER_UNSIGNED) _downloaded.remove(new UpdateItem(ROUTER_SIGNED_SU3, ""));
// remove available from other type
UpdateItem altui = new UpdateItem(ROUTER_SIGNED_SU3, id);
Version old = _available.get(altui);
if (old != null && old.compareTo(ver) <= 0)
_available.remove(altui);
// ... and declare the alt downloaded as well
_downloaded.put(altui, ver);
} else if (type == ROUTER_SIGNED_SU3) {
_downloaded.remove(new UpdateItem(ROUTER_SIGNED, "")); _downloaded.remove(new UpdateItem(ROUTER_SIGNED, ""));
_downloaded.remove(new UpdateItem(ROUTER_UNSIGNED, ""));
// remove available from other type
UpdateItem altui = new UpdateItem(ROUTER_SIGNED, id);
Version old = _available.get(altui);
if (old != null && old.compareTo(ver) <= 0)
_available.remove(altui);
// ... and declare the alt downloaded as well
_downloaded.put(altui, ver);
} else if (type == ROUTER_UNSIGNED) {
_downloaded.remove(new UpdateItem(ROUTER_SIGNED, ""));
_downloaded.remove(new UpdateItem(ROUTER_SIGNED_SU3, ""));
}
Version old = _available.get(ui); Version old = _available.get(ui);
if (old != null && old.compareTo(ver) <= 0) if (old != null && old.compareTo(ver) <= 0)
_available.remove(ui); _available.remove(ui);
@ -1018,6 +1066,7 @@ public class ConsoleUpdateManager implements UpdateManager {
break; break;
case ROUTER_SIGNED: case ROUTER_SIGNED:
{ // avoid dup variables in next case
String URLs = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_URL, ConfigUpdateHandler.DEFAULT_UPDATE_URL); String URLs = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_URL, ConfigUpdateHandler.DEFAULT_UPDATE_URL);
StringTokenizer tok = new StringTokenizer(URLs, " ,\r\n"); StringTokenizer tok = new StringTokenizer(URLs, " ,\r\n");
List<URI> rv = new ArrayList(); List<URI> rv = new ArrayList();
@ -1028,6 +1077,21 @@ public class ConsoleUpdateManager implements UpdateManager {
} }
Collections.shuffle(rv, _context.random()); Collections.shuffle(rv, _context.random());
return rv; return rv;
}
case ROUTER_SIGNED_SU3:
{
String URLs = ConfigUpdateHandler.SU3_UPDATE_URLS;
StringTokenizer tok = new StringTokenizer(URLs, " ,\r\n");
List<URI> rv = new ArrayList();
while (tok.hasMoreTokens()) {
try {
rv.add(new URI(tok.nextToken().trim()));
} catch (URISyntaxException use) {}
}
Collections.shuffle(rv, _context.random());
return rv;
}
case ROUTER_UNSIGNED: case ROUTER_UNSIGNED:
String url = _context.getProperty(ConfigUpdateHandler.PROP_ZIP_URL); String url = _context.getProperty(ConfigUpdateHandler.PROP_ZIP_URL);
@ -1072,14 +1136,59 @@ public class ConsoleUpdateManager implements UpdateManager {
* @return success * @return success
*/ */
private boolean handleSudFile(URI uri, String actualVersion, File f) { private boolean handleSudFile(URI uri, String actualVersion, File f) {
return handleRouterFile(uri, actualVersion, f, false);
}
/**
* @return success
* @since 0.9.9
*/
private boolean handleSu3File(URI uri, String actualVersion, File f) {
return handleRouterFile(uri, actualVersion, f, true);
}
/**
* Process sud, su2, or su3
* @return success
* @since 0.9.9
*/
private boolean handleRouterFile(URI uri, String actualVersion, File f, boolean isSU3) {
String url = uri.toString(); String url = uri.toString();
// Process the .sud/.su2 file
updateStatus("<b>" + _("Update downloaded") + "</b>"); updateStatus("<b>" + _("Update downloaded") + "</b>");
TrustedUpdate up = new TrustedUpdate(_context);
File to = new File(_context.getRouterDir(), Router.UPDATE_FILE); File to = new File(_context.getRouterDir(), Router.UPDATE_FILE);
String err = up.migrateVerified(RouterVersion.VERSION, f, to); String err;
/////////// // Process the file
// caller must delete now.. why? if (isSU3) {
SU3File up = new SU3File(_context, f);
File temp = new File(_context.getTempDir(), "su3out-" + _context.random().nextLong() + ".zip");
try {
if (up.verifyAndMigrate(temp)) {
String ver = up.getVersionString();
int type = up.getContentType();
if (ver == null || VersionComparator.comp(RouterVersion.VERSION, ver) >= 0)
err = "Old version " + ver;
else if (type != SU3File.CONTENT_ROUTER)
err = "Bad su3 content type " + type;
else if (!FileUtil.copy(temp, to, true, false))
err = "Failed copy to " + to;
else
err = null; // success
} else {
err = "Signature failed, signer " + DataHelper.stripHTML(up.getSignerString()) +
' ' + up.getSigType();
}
} catch (IOException ioe) {
_log.error("SU3 extract error", ioe);
err = DataHelper.stripHTML(ioe.toString());
} finally {
temp.delete();
}
} else {
TrustedUpdate up = new TrustedUpdate(_context);
err = up.migrateVerified(RouterVersion.VERSION, f, to);
}
// caller must delete.. could be an active torrent
//f.delete(); //f.delete();
if (err == null) { if (err == null) {
String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY); String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY);
@ -1346,6 +1455,8 @@ public class ConsoleUpdateManager implements UpdateManager {
@Override @Override
public String toString() { public String toString() {
if ("".equals(id))
return "UpdateItem " + type;
return "UpdateItem " + type + ' ' + id; return "UpdateItem " + type + ' ' + id;
} }
} }

View File

@ -48,13 +48,10 @@ class DummyHandler implements Checker, Updater {
private final long _delay; private final long _delay;
public DummyRunner(RouterContext ctx, ConsoleUpdateManager mgr, long maxTime) { public DummyRunner(RouterContext ctx, ConsoleUpdateManager mgr, long maxTime) {
super(ctx, mgr, Collections.EMPTY_LIST); super(ctx, mgr, UpdateType.TYPE_DUMMY, Collections.EMPTY_LIST);
_delay = maxTime; _delay = maxTime;
} }
@Override
public UpdateType getType() { return UpdateType.TYPE_DUMMY; }
@Override @Override
public UpdateMethod getMethod() { return UpdateMethod.METHOD_DUMMY; } public UpdateMethod getMethod() { return UpdateMethod.METHOD_DUMMY; }

View File

@ -32,6 +32,7 @@ import net.i2p.util.EepHead;
import net.i2p.util.FileUtil; import net.i2p.util.FileUtil;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
import net.i2p.util.SSLEepGet;
/** /**
* Task to fetch updates to the news.xml, and to keep * Task to fetch updates to the news.xml, and to keep
@ -50,7 +51,7 @@ class NewsFetcher extends UpdateRunner {
private static final String TEMP_NEWS_FILE = "news.xml.temp"; private static final String TEMP_NEWS_FILE = "news.xml.temp";
public NewsFetcher(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris) { public NewsFetcher(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris) {
super(ctx, mgr, uris); super(ctx, mgr, NEWS, uris);
_newsFile = new File(ctx.getRouterDir(), NewsHelper.NEWS_FILE); _newsFile = new File(ctx.getRouterDir(), NewsHelper.NEWS_FILE);
_tempFile = new File(ctx.getTempDir(), "tmp-" + ctx.random().nextLong() + TEMP_NEWS_FILE); _tempFile = new File(ctx.getTempDir(), "tmp-" + ctx.random().nextLong() + TEMP_NEWS_FILE);
long lastMod = NewsHelper.lastChecked(ctx); long lastMod = NewsHelper.lastChecked(ctx);
@ -73,7 +74,7 @@ class NewsFetcher extends UpdateRunner {
} }
public void fetchNews() { public void fetchNews() {
boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue(); boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY_NEWS, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY_NEWS);
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
int proxyPort = ConfigUpdateHandler.proxyPort(_context); int proxyPort = ConfigUpdateHandler.proxyPort(_context);
@ -88,6 +89,9 @@ class NewsFetcher extends UpdateRunner {
EepGet get; EepGet get;
if (shouldProxy) if (shouldProxy)
get = new EepGet(_context, true, proxyHost, proxyPort, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified); get = new EepGet(_context, true, proxyHost, proxyPort, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified);
else if ("https".equals(uri.getScheme()))
// no constructor w/ last mod check
get = new SSLEepGet(_context, _tempFile.getAbsolutePath(), newsURL);
else else
get = new EepGet(_context, false, null, 0, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified); get = new EepGet(_context, false, null, 0, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified);
get.addStatusListener(this); get.addStatusListener(this);
@ -113,9 +117,11 @@ class NewsFetcher extends UpdateRunner {
private static final String MIN_JAVA_VERSION_KEY = "minjavaversion"; private static final String MIN_JAVA_VERSION_KEY = "minjavaversion";
private static final String SUD_KEY = "sudtorrent"; private static final String SUD_KEY = "sudtorrent";
private static final String SU2_KEY = "su2torrent"; private static final String SU2_KEY = "su2torrent";
// following are unused private static final String SU3_KEY = "su3torrent";
private static final String CLEARNET_SUD_KEY = "sudclearnet"; private static final String CLEARNET_SUD_KEY = "sudclearnet";
private static final String CLEARNET_SU2_KEY = "su2clearnet"; private static final String CLEARNET_SU2_KEY = "su2clearnet";
private static final String CLEARNET_HTTP_SU3_KEY = "su3clearnet";
private static final String CLEARNET_HTTPS_SU3_KEY = "su3ssl";
private static final String I2P_SUD_KEY = "sudi2p"; private static final String I2P_SUD_KEY = "sudi2p";
private static final String I2P_SU2_KEY = "su2i2p"; private static final String I2P_SU2_KEY = "su2i2p";
@ -175,20 +181,24 @@ class NewsFetcher extends UpdateRunner {
// and look for a second entry with clearnet URLs // and look for a second entry with clearnet URLs
// TODO clearnet URLs, notify with HTTP_CLEARNET and/or HTTPS_CLEARNET // TODO clearnet URLs, notify with HTTP_CLEARNET and/or HTTPS_CLEARNET
Map<UpdateMethod, List<URI>> sourceMap = new HashMap(4); Map<UpdateMethod, List<URI>> sourceMap = new HashMap(4);
// Must do su3 first
if (ConfigUpdateHandler.USE_SU3_UPDATE) {
sourceMap.put(HTTP, _mgr.getUpdateURLs(ROUTER_SIGNED_SU3, "", HTTP));
addMethod(TORRENT, args.get(SU3_KEY), sourceMap);
addMethod(HTTP_CLEARNET, args.get(CLEARNET_HTTP_SU3_KEY), sourceMap);
addMethod(HTTPS_CLEARNET, args.get(CLEARNET_HTTPS_SU3_KEY), sourceMap);
// notify about all sources at once
_mgr.notifyVersionAvailable(this, _currentURI, ROUTER_SIGNED_SU3,
"", sourceMap, ver, "");
sourceMap.clear();
}
// now do sud/su2
sourceMap.put(HTTP, _mgr.getUpdateURLs(ROUTER_SIGNED, "", HTTP)); sourceMap.put(HTTP, _mgr.getUpdateURLs(ROUTER_SIGNED, "", HTTP));
String key = FileUtil.isPack200Supported() ? SU2_KEY : SUD_KEY; String key = FileUtil.isPack200Supported() ? SU2_KEY : SUD_KEY;
String murl = args.get(key); addMethod(TORRENT, args.get(key), sourceMap);
if (murl != null) {
List<URI> uris = tokenize(murl);
if (!uris.isEmpty()) {
Collections.shuffle(uris, _context.random());
sourceMap.put(TORRENT, uris);
}
}
// notify about all sources at once // notify about all sources at once
_mgr.notifyVersionAvailable(this, _currentURI, _mgr.notifyVersionAvailable(this, _currentURI, ROUTER_SIGNED,
ROUTER_SIGNED, "", sourceMap, "", sourceMap, ver, "");
ver, "");
} else { } else {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Our version is current"); _log.debug("Our version is current");
@ -292,6 +302,21 @@ class NewsFetcher extends UpdateRunner {
return rv; return rv;
} }
/**
* Parse URLs and add to the map
* @param urls may be null
* @since 0.9.9
*/
private void addMethod(UpdateMethod method, String urls, Map<UpdateMethod, List<URI>> map) {
if (urls != null) {
List<URI> uris = tokenize(urls);
if (!uris.isEmpty()) {
Collections.shuffle(uris, _context.random());
map.put(method, uris);
}
}
}
/** override to prevent status update */ /** override to prevent status update */
@Override @Override
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {} public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {}

View File

@ -35,16 +35,13 @@ class PluginUpdateChecker extends UpdateRunner {
public PluginUpdateChecker(RouterContext ctx, ConsoleUpdateManager mgr, public PluginUpdateChecker(RouterContext ctx, ConsoleUpdateManager mgr,
List<URI> uris, String appName, String oldVersion ) { List<URI> uris, String appName, String oldVersion ) {
super(ctx, mgr, uris, oldVersion); super(ctx, mgr, UpdateType.PLUGIN, uris, oldVersion);
if (!uris.isEmpty()) if (!uris.isEmpty())
_currentURI = uris.get(0); _currentURI = uris.get(0);
_appName = appName; _appName = appName;
_oldVersion = oldVersion; _oldVersion = oldVersion;
} }
@Override
public UpdateType getType() { return UpdateType.PLUGIN; }
@Override @Override
public String getID() { return _appName; } public String getID() { return _appName; }

View File

@ -60,7 +60,7 @@ class PluginUpdateRunner extends UpdateRunner {
public PluginUpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris, public PluginUpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris,
String appName, String oldVersion ) { String appName, String oldVersion ) {
super(ctx, mgr, uris); super(ctx, mgr, UpdateType.PLUGIN, uris);
if (uris.isEmpty()) if (uris.isEmpty())
throw new IllegalArgumentException("uri cannot be empty"); throw new IllegalArgumentException("uri cannot be empty");
else else
@ -70,12 +70,6 @@ class PluginUpdateRunner extends UpdateRunner {
_oldVersion = oldVersion; _oldVersion = oldVersion;
} }
@Override
public UpdateType getType() {
return UpdateType.PLUGIN;
}
@Override @Override
public URI getURI() { return _uri; } public URI getURI() { return _uri; }
@ -104,7 +98,7 @@ class PluginUpdateRunner extends UpdateRunner {
} else { } else {
updateStatus("<b>" + _("Downloading plugin from {0}", _xpi2pURL) + "</b>"); updateStatus("<b>" + _("Downloading plugin from {0}", _xpi2pURL) + "</b>");
// use the same settings as for updater // use the same settings as for updater
boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue(); boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
int proxyPort = ConfigUpdateHandler.proxyPort(_context); int proxyPort = ConfigUpdateHandler.proxyPort(_context);
try { try {

View File

@ -28,17 +28,10 @@ class UnsignedUpdateChecker extends UpdateRunner {
public UnsignedUpdateChecker(RouterContext ctx, ConsoleUpdateManager mgr, public UnsignedUpdateChecker(RouterContext ctx, ConsoleUpdateManager mgr,
List<URI> uris, long lastUpdateTime) { List<URI> uris, long lastUpdateTime) {
super(ctx, mgr, uris); super(ctx, mgr, UpdateType.ROUTER_UNSIGNED, uris);
_ms = lastUpdateTime; _ms = lastUpdateTime;
} }
//////// begin UpdateTask methods
@Override
public UpdateType getType() { return UpdateType.ROUTER_UNSIGNED; }
//////// end UpdateTask methods
@Override @Override
public void run() { public void run() {
_isRunning = true; _isRunning = true;

View File

@ -25,16 +25,12 @@ import net.i2p.util.Log;
class UnsignedUpdateRunner extends UpdateRunner { class UnsignedUpdateRunner extends UpdateRunner {
public UnsignedUpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris) { public UnsignedUpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris) {
super(ctx, mgr, uris); super(ctx, mgr, ROUTER_UNSIGNED, uris);
if (!uris.isEmpty()) if (!uris.isEmpty())
_currentURI = uris.get(0); _currentURI = uris.get(0);
} }
@Override
public UpdateType getType() { return ROUTER_UNSIGNED; }
/** Get the file */ /** Get the file */
@Override @Override
protected void update() { protected void update() {

View File

@ -4,7 +4,10 @@ import java.net.URI;
import java.util.List; import java.util.List;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.router.web.ConfigUpdateHandler;
import net.i2p.update.*; import net.i2p.update.*;
import static net.i2p.update.UpdateType.*;
import static net.i2p.update.UpdateMethod.*;
/** /**
* <p>Handles the request to update the router by firing one or more * <p>Handles the request to update the router by firing one or more
@ -38,10 +41,13 @@ class UpdateHandler implements Updater {
*/ */
public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources, public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources,
String id, String newVersion, long maxTime) { String id, String newVersion, long maxTime) {
if (type != UpdateType.ROUTER_SIGNED || boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
method != UpdateMethod.HTTP || updateSources.isEmpty()) if ((type != ROUTER_SIGNED && type != ROUTER_SIGNED_SU3) ||
(shouldProxy && method != HTTP) ||
((!shouldProxy) && method != HTTP_CLEARNET && method != HTTPS_CLEARNET) ||
updateSources.isEmpty())
return null; return null;
UpdateRunner update = new UpdateRunner(_context, _mgr, updateSources); UpdateRunner update = new UpdateRunner(_context, _mgr, type, method, updateSources);
// set status before thread to ensure UI feedback // set status before thread to ensure UI feedback
_mgr.notifyProgress(update, "<b>" + _mgr._("Updating") + "</b>"); _mgr.notifyProgress(update, "<b>" + _mgr._("Updating") + "</b>");
return update; return update;

View File

@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import net.i2p.crypto.TrustedUpdate; import net.i2p.crypto.TrustedUpdate;
@ -13,10 +14,12 @@ import net.i2p.router.RouterContext;
import net.i2p.router.RouterVersion; import net.i2p.router.RouterVersion;
import net.i2p.router.web.ConfigUpdateHandler; import net.i2p.router.web.ConfigUpdateHandler;
import net.i2p.update.*; import net.i2p.update.*;
import static net.i2p.update.UpdateMethod.*;
import net.i2p.util.EepGet; import net.i2p.util.EepGet;
import net.i2p.util.I2PAppThread; import net.i2p.util.I2PAppThread;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.PartialEepGet; import net.i2p.util.PartialEepGet;
import net.i2p.util.SSLEepGet;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
/** /**
@ -30,6 +33,8 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
protected final RouterContext _context; protected final RouterContext _context;
protected final Log _log; protected final Log _log;
protected final ConsoleUpdateManager _mgr; protected final ConsoleUpdateManager _mgr;
protected final UpdateType _type;
protected final UpdateMethod _method;
protected final List<URI> _urls; protected final List<URI> _urls;
protected final String _updateFile; protected final String _updateFile;
protected volatile boolean _isRunning; protected volatile boolean _isRunning;
@ -53,20 +58,42 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
/** /**
* Uses router version for partial checks * Uses router version for partial checks
*/ */
public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris) { public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, UpdateType type, List<URI> uris) {
this(ctx, mgr, uris, RouterVersion.VERSION); this(ctx, mgr, type, uris, RouterVersion.VERSION);
}
/**
* Uses router version for partial checks
* @since 0.9.9
*/
public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, UpdateType type,
UpdateMethod method, List<URI> uris) {
this(ctx, mgr, type, method, uris, RouterVersion.VERSION);
} }
/** /**
* @param currentVersion used for partial checks * @param currentVersion used for partial checks
* @since 0.9.7 * @since 0.9.7
*/ */
public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris, String currentVersion) { public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, UpdateType type,
List<URI> uris, String currentVersion) {
this(ctx, mgr, type, HTTP, uris, currentVersion);
}
/**
* @param method HTTP, HTTP_CLEARNET, or HTTPS_CLEARNET
* @param currentVersion used for partial checks
* @since 0.9.9
*/
public UpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, UpdateType type,
UpdateMethod method, List<URI> uris, String currentVersion) {
super("Update Runner"); super("Update Runner");
setDaemon(true); setDaemon(true);
_context = ctx; _context = ctx;
_log = ctx.logManager().getLog(getClass()); _log = ctx.logManager().getLog(getClass());
_mgr = mgr; _mgr = mgr;
_type = type;
_method = method;
_urls = uris; _urls = uris;
_baos = new ByteArrayOutputStream(TrustedUpdate.HEADER_BYTES); _baos = new ByteArrayOutputStream(TrustedUpdate.HEADER_BYTES);
_updateFile = (new File(ctx.getTempDir(), "update" + ctx.random().nextInt() + ".tmp")).getAbsolutePath(); _updateFile = (new File(ctx.getTempDir(), "update" + ctx.random().nextInt() + ".tmp")).getAbsolutePath();
@ -82,9 +109,9 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
interrupt(); interrupt();
} }
public UpdateType getType() { return UpdateType.ROUTER_SIGNED; } public UpdateType getType() { return _type; }
public UpdateMethod getMethod() { return UpdateMethod.HTTP; } public UpdateMethod getMethod() { return _method; }
public URI getURI() { return _currentURI; } public URI getURI() { return _currentURI; }
@ -117,9 +144,32 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
// Alternative: In bytesTransferred(), Check the data in the output file after // Alternative: In bytesTransferred(), Check the data in the output file after
// we've received at least 56 bytes. Need a cancel() method in EepGet ? // we've received at least 56 bytes. Need a cancel() method in EepGet ?
boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue(); boolean shouldProxy;
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); String proxyHost;
int proxyPort = ConfigUpdateHandler.proxyPort(_context); int proxyPort;
boolean isSSL = false;
if (_method == HTTP) {
shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
if (shouldProxy) {
proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
proxyPort = ConfigUpdateHandler.proxyPort(_context);
} else {
// TODO, wrong method, fail
proxyHost = null;
proxyPort = 0;
}
} else if (_method == HTTP_CLEARNET) {
shouldProxy = false;
proxyHost = null;
proxyPort = 0;
} else if (_method == HTTPS_CLEARNET) {
shouldProxy = false;
proxyHost = null;
proxyPort = 0;
isSSL = true;
} else {
throw new IllegalArgumentException();
}
if (_urls.isEmpty()) { if (_urls.isEmpty()) {
// not likely, don't bother translating // not likely, don't bother translating
@ -132,12 +182,24 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
for (URI uri : _urls) { for (URI uri : _urls) {
_currentURI = uri; _currentURI = uri;
String updateURL = uri.toString(); String updateURL = uri.toString();
if ((_method == HTTP && !"http".equals(uri.getScheme())) ||
(_method == HTTP_CLEARNET && !"http".equals(uri.getScheme())) ||
(_method == HTTPS_CLEARNET && !"https".equals(uri.getScheme())) ||
uri.getHost() == null ||
(_method != HTTP && uri.getHost().toLowerCase(Locale.US).endsWith(".i2p"))) {
if (_log.shouldLog(Log.WARN))
_log.warn("Bad update URI " + uri + " for method " + _method);
continue;
}
updateStatus("<b>" + _("Updating from {0}", linkify(updateURL)) + "</b>"); updateStatus("<b>" + _("Updating from {0}", linkify(updateURL)) + "</b>");
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Selected update URL: " + updateURL); _log.debug("Selected update URL: " + updateURL);
// Check the first 56 bytes for the version // Check the first 56 bytes for the version
if (shouldProxy) { // FIXME PartialEepGet works with clearnet but not with SSL
_newVersion = null;
if (!isSSL) {
_isPartial = true; _isPartial = true;
_baos.reset(); _baos.reset();
try { try {
@ -157,6 +219,8 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
if (shouldProxy) if (shouldProxy)
// 40 retries!! // 40 retries!!
_get = new EepGet(_context, proxyHost, proxyPort, 40, _updateFile, updateURL, false); _get = new EepGet(_context, proxyHost, proxyPort, 40, _updateFile, updateURL, false);
else if (isSSL)
_get = new SSLEepGet(_context, _updateFile, updateURL);
else else
_get = new EepGet(_context, 1, _updateFile, updateURL, false); _get = new EepGet(_context, 1, _updateFile, updateURL, false);
_get.addStatusListener(UpdateRunner.this); _get.addStatusListener(UpdateRunner.this);
@ -208,6 +272,9 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
return; return;
} }
// FIXME if we didn't do a partial, we don't know
if (_newVersion == null)
_newVersion = "unknown";
File tmp = new File(_updateFile); File tmp = new File(_updateFile);
if (_mgr.notifyComplete(this, _newVersion, tmp)) if (_mgr.notifyComplete(this, _newVersion, tmp))
this.done = true; this.done = true;

View File

@ -14,8 +14,6 @@ public class ConfigTunnelsHelper extends HelperBase {
private static final String HOPS = ngettext("1 hop", "{0} hops"); private static final String HOPS = ngettext("1 hop", "{0} hops");
private static final String TUNNELS = ngettext("1 tunnel", "{0} tunnels"); private static final String TUNNELS = ngettext("1 tunnel", "{0} tunnels");
static final String PROP_ADVANCED = "routerconsole.advanced";
public String getForm() { public String getForm() {
StringBuilder buf = new StringBuilder(1024); StringBuilder buf = new StringBuilder(1024);
// HTML: <input> cannot be inside a <table> // HTML: <input> cannot be inside a <table>
@ -69,7 +67,7 @@ public class ConfigTunnelsHelper extends HelperBase {
private void renderForm(StringBuilder buf, int index, String prefix, String name, TunnelPoolSettings in, TunnelPoolSettings out) { private void renderForm(StringBuilder buf, int index, String prefix, String name, TunnelPoolSettings in, TunnelPoolSettings out) {
boolean advanced = _context.getBooleanProperty(PROP_ADVANCED); boolean advanced = isAdvanced();
buf.append("<tr><th colspan=\"3\"><a name=\"").append(prefix).append("\">"); buf.append("<tr><th colspan=\"3\"><a name=\"").append(prefix).append("\">");
buf.append(name).append("</a></th></tr>\n"); buf.append(name).append("</a></th></tr>\n");

View File

@ -1,5 +1,6 @@
package net.i2p.router.web; package net.i2p.router.web;
import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -22,6 +23,7 @@ public class ConfigUpdateHandler extends FormHandler {
private String _proxyHost; private String _proxyHost;
private String _proxyPort; private String _proxyPort;
private boolean _updateThroughProxy; private boolean _updateThroughProxy;
private boolean _newsThroughProxy;
private String _trustedKeys; private String _trustedKeys;
private boolean _updateUnsigned; private boolean _updateUnsigned;
private String _zipURL; private String _zipURL;
@ -36,7 +38,11 @@ public class ConfigUpdateHandler extends FormHandler {
public static final String PROP_UPDATE_POLICY = "router.updatePolicy"; public static final String PROP_UPDATE_POLICY = "router.updatePolicy";
public static final String DEFAULT_UPDATE_POLICY = "download"; public static final String DEFAULT_UPDATE_POLICY = "download";
public static final String PROP_SHOULD_PROXY = "router.updateThroughProxy"; public static final String PROP_SHOULD_PROXY = "router.updateThroughProxy";
public static final String DEFAULT_SHOULD_PROXY = Boolean.TRUE.toString(); public static final boolean DEFAULT_SHOULD_PROXY = true;
/** @since 0.9.9 */
public static final String PROP_SHOULD_PROXY_NEWS = "router.fetchNewsThroughProxy";
/** @since 0.9.9 */
public static final boolean DEFAULT_SHOULD_PROXY_NEWS = true;
public static final String PROP_PROXY_HOST = "router.updateProxyHost"; public static final String PROP_PROXY_HOST = "router.updateProxyHost";
public static final String DEFAULT_PROXY_HOST = "127.0.0.1"; public static final String DEFAULT_PROXY_HOST = "127.0.0.1";
public static final String PROP_PROXY_PORT = "router.updateProxyPort"; public static final String PROP_PROXY_PORT = "router.updateProxyPort";
@ -50,6 +56,7 @@ public class ConfigUpdateHandler extends FormHandler {
public static final String PROP_ZIP_URL = "router.updateUnsignedURL"; public static final String PROP_ZIP_URL = "router.updateUnsignedURL";
public static final String PROP_UPDATE_URL = "router.updateURL"; public static final String PROP_UPDATE_URL = "router.updateURL";
/** /**
* Changed as of release 0.8 to support both .sud and .su2 * Changed as of release 0.8 to support both .sud and .su2
* Some JVMs (IcedTea) don't have pack200 * Some JVMs (IcedTea) don't have pack200
@ -75,6 +82,10 @@ public class ConfigUpdateHandler extends FormHandler {
"http://update.killyourtv.i2p/i2pupdate.sud\r\n" + "http://update.killyourtv.i2p/i2pupdate.sud\r\n" +
"http://update.postman.i2p/i2pupdate.sud" ; "http://update.postman.i2p/i2pupdate.sud" ;
/**
* These are only for .sud and .su2.
* Do NOT use this for .su3
*/
public static final String DEFAULT_UPDATE_URL; public static final String DEFAULT_UPDATE_URL;
static { static {
if (FileUtil.isPack200Supported()) if (FileUtil.isPack200Supported())
@ -83,6 +94,34 @@ public class ConfigUpdateHandler extends FormHandler {
DEFAULT_UPDATE_URL = NO_PACK200_URLS; DEFAULT_UPDATE_URL = NO_PACK200_URLS;
} }
private static final String SU3_CERT_DIR = "certificates/router";
/**
* Only enabled if we have pack200 and trusted public key certificates installed
* @since 0.9.9
*/
public static final boolean USE_SU3_UPDATE;
static {
String[] files = (new File(I2PAppContext.getGlobalContext().getBaseDir(), SU3_CERT_DIR)).list();
USE_SU3_UPDATE = FileUtil.isPack200Supported() && files != null && files.length > 0;
}
private static final String DEFAULT_SU3_UPDATE_URLS =
"http://echelon.i2p/i2p/i2pupdate.su3\r\n" +
"http://inr.i2p/i2p/i2pupdate.su3\r\n" +
"http://meeh.i2p/i2pupdate/i2pupdate.su3\r\n" +
"http://stats.i2p/i2p/i2pupdate.su3\r\n" +
"http://www.i2p2.i2p/_static/i2pupdate.su3\r\n" +
"http://update.dg.i2p/files/i2pupdate.su3\r\n" +
"http://update.killyourtv.i2p/i2pupdate.su3\r\n" +
"http://update.postman.i2p/i2pupdate.su3" ;
/**
* Empty string if disabled. Cannot be overridden by config.
* @since 0.9.9
*/
public static final String SU3_UPDATE_URLS = USE_SU3_UPDATE ? DEFAULT_SU3_UPDATE_URLS : "";
public static final String PROP_TRUSTED_KEYS = "router.trustedUpdateKeys"; public static final String PROP_TRUSTED_KEYS = "router.trustedUpdateKeys";
/** /**
@ -130,6 +169,8 @@ public class ConfigUpdateHandler extends FormHandler {
Map<String, String> changes = new HashMap(); Map<String, String> changes = new HashMap();
if ( (_newsURL != null) && (_newsURL.length() > 0) ) { if ( (_newsURL != null) && (_newsURL.length() > 0) ) {
if (_newsURL.startsWith("https"))
_newsThroughProxy = false;
String oldURL = ConfigUpdateHelper.getNewsURL(_context); String oldURL = ConfigUpdateHelper.getNewsURL(_context);
if ( (oldURL == null) || (!_newsURL.equals(oldURL)) ) { if ( (oldURL == null) || (!_newsURL.equals(oldURL)) ) {
changes.put(PROP_NEWS_URL, _newsURL); changes.put(PROP_NEWS_URL, _newsURL);
@ -155,8 +196,9 @@ public class ConfigUpdateHandler extends FormHandler {
} }
} }
changes.put(PROP_SHOULD_PROXY, "" + _updateThroughProxy); changes.put(PROP_SHOULD_PROXY, Boolean.toString(_updateThroughProxy));
changes.put(PROP_UPDATE_UNSIGNED, "" + _updateUnsigned); changes.put(PROP_SHOULD_PROXY_NEWS, Boolean.toString(_newsThroughProxy));
changes.put(PROP_UPDATE_UNSIGNED, Boolean.toString(_updateUnsigned));
String oldFreqStr = _context.getProperty(PROP_REFRESH_FREQUENCY, DEFAULT_REFRESH_FREQUENCY); String oldFreqStr = _context.getProperty(PROP_REFRESH_FREQUENCY, DEFAULT_REFRESH_FREQUENCY);
long oldFreq = DEFAULT_REFRESH_FREQ; long oldFreq = DEFAULT_REFRESH_FREQ;
@ -218,4 +260,6 @@ public class ConfigUpdateHandler extends FormHandler {
public void setProxyPort(String port) { _proxyPort = port; } public void setProxyPort(String port) { _proxyPort = port; }
public void setUpdateUnsigned(String foo) { _updateUnsigned = true; } public void setUpdateUnsigned(String foo) { _updateUnsigned = true; }
public void setZipURL(String url) { _zipURL = url; } public void setZipURL(String url) { _zipURL = url; }
/** @since 0.9.9 */
public void setNewsThroughProxy(String foo) { _newsThroughProxy = true; }
} }

View File

@ -73,13 +73,20 @@ public class ConfigUpdateHelper extends HelperBase {
} }
public String getUpdateThroughProxy() { public String getUpdateThroughProxy() {
String proxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY); if (_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY))
if (Boolean.parseBoolean(proxy))
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" checked=\"checked\" >"; return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" checked=\"checked\" >";
else else
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" >"; return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" >";
} }
/** @since 0.9.9 */
public String getNewsThroughProxy() {
if (_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY_NEWS, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY_NEWS))
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"newsThroughProxy\" checked=\"checked\" >";
else
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"newsThroughProxy\" >";
}
public String getUpdateUnsigned() { public String getUpdateUnsigned() {
if (_context.getBooleanProperty(ConfigUpdateHandler.PROP_UPDATE_UNSIGNED)) if (_context.getBooleanProperty(ConfigUpdateHandler.PROP_UPDATE_UNSIGNED))
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" checked=\"checked\" >"; return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" checked=\"checked\" >";

View File

@ -11,6 +11,8 @@ public abstract class HelperBase {
protected RouterContext _context; protected RouterContext _context;
protected Writer _out; protected Writer _out;
static final String PROP_ADVANCED = "routerconsole.advanced";
/** /**
* Configure this bean to query a particular router context * Configure this bean to query a particular router context
* *
@ -25,6 +27,11 @@ public abstract class HelperBase {
} }
} }
/** @since 0.9.9 */
public boolean isAdvanced() {
return _context.getBooleanProperty(PROP_ADVANCED);
}
/** might be useful in the jsp's */ /** might be useful in the jsp's */
//public RouterContext getContext() { return _context; } //public RouterContext getContext() { return _context; }

View File

@ -49,6 +49,7 @@ public class NewsHelper extends ContentHelper {
ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance(); ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance();
if (mgr == null) return false; if (mgr == null) return false;
return mgr.isUpdateInProgress(ROUTER_SIGNED) || return mgr.isUpdateInProgress(ROUTER_SIGNED) ||
mgr.isUpdateInProgress(ROUTER_SIGNED_SU3) ||
mgr.isUpdateInProgress(ROUTER_UNSIGNED) || mgr.isUpdateInProgress(ROUTER_UNSIGNED) ||
mgr.isUpdateInProgress(TYPE_DUMMY); mgr.isUpdateInProgress(TYPE_DUMMY);
} }
@ -60,7 +61,8 @@ public class NewsHelper extends ContentHelper {
public static boolean isUpdateAvailable() { public static boolean isUpdateAvailable() {
ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance(); ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance();
if (mgr == null) return false; if (mgr == null) return false;
return mgr.getUpdateAvailable(ROUTER_SIGNED) != null; return mgr.getUpdateAvailable(ROUTER_SIGNED) != null ||
mgr.getUpdateAvailable(ROUTER_SIGNED_SU3) != null;
} }
/** /**
@ -71,6 +73,9 @@ public class NewsHelper extends ContentHelper {
public static String updateVersion() { public static String updateVersion() {
ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance(); ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance();
if (mgr == null) return null; if (mgr == null) return null;
String rv = mgr.getUpdateAvailable(ROUTER_SIGNED_SU3);
if (rv != null)
return rv;
return mgr.getUpdateAvailable(ROUTER_SIGNED); return mgr.getUpdateAvailable(ROUTER_SIGNED);
} }
@ -93,6 +98,9 @@ public class NewsHelper extends ContentHelper {
public static String updateVersionDownloaded() { public static String updateVersionDownloaded() {
ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance(); ConsoleUpdateManager mgr = ConsoleUpdateManager.getInstance();
if (mgr == null) return null; if (mgr == null) return null;
String rv = mgr.getUpdateDownloaded(ROUTER_SIGNED_SU3);
if (rv != null)
return rv;
return mgr.getUpdateDownloaded(ROUTER_SIGNED); return mgr.getUpdateDownloaded(ROUTER_SIGNED);
} }

View File

@ -0,0 +1,37 @@
package net.i2p.router.web;
import java.util.Date;
import net.i2p.data.DataHelper;
import net.i2p.data.RouterAddress;
import net.i2p.data.RouterInfo;
import net.i2p.data.Signature;
/**
* Sign a statement about this router.
* @since 0.9.8
*/
public class ProofHelper extends HelperBase {
public String getProof() {
StringBuilder buf = new StringBuilder(512);
RouterInfo us = _context.router().getRouterInfo();
buf.append("Hash: ").append(us.getIdentity().calculateHash().toBase64()).append('\n');
//buf.append("Ident: ").append(us.getIdentity().toBase64()).append('\n');
for (RouterAddress addr : us.getAddresses()) {
buf.append(addr.getTransportStyle()).append(": ").append(addr.getHost()).append('\n');
}
buf.append("Caps: ").append(us.getCapabilities()).append('\n');
buf.append("Date: ").append(new Date()); // no trailing newline
String msg = buf.toString();
byte[] data = DataHelper.getUTF8(msg);
Signature sig = _context.dsa().sign(data, _context.keyManager().getSigningPrivateKey());
buf.setLength(0);
buf.append("---BEGIN I2P SIGNED MESSAGE---\n");
buf.append(msg);
buf.append("\n---BEGIN I2P SIGNATURE---\n");
buf.append(sig.toBase64());
buf.append("\n---END I2P SIGNATURE---");
return buf.toString();
}
}

View File

@ -27,6 +27,7 @@ import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState; import net.i2p.app.ClientAppState;
import static net.i2p.app.ClientAppState.*; import static net.i2p.app.ClientAppState.*;
import net.i2p.apps.systray.SysTray; import net.i2p.apps.systray.SysTray;
import net.i2p.crypto.KeyStoreUtil;
import net.i2p.data.Base32; import net.i2p.data.Base32;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.jetty.I2PLogger; import net.i2p.jetty.I2PLogger;
@ -38,8 +39,6 @@ import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread; import net.i2p.util.I2PAppThread;
import net.i2p.util.PortMapper; import net.i2p.util.PortMapper;
import net.i2p.util.SecureDirectory; import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.ShellCommand;
import net.i2p.util.SystemVersion; import net.i2p.util.SystemVersion;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
@ -677,12 +676,6 @@ public class RouterConsoleRunner implements RouterApp {
System.err.println("Console SSL error, must set " + PROP_KEY_PASSWORD + " in " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath()); System.err.println("Console SSL error, must set " + PROP_KEY_PASSWORD + " in " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath());
return rv; return rv;
} }
File dir = ks.getParentFile();
if (!dir.exists()) {
File sdir = new SecureDirectory(dir.getAbsolutePath());
if (!sdir.mkdir())
return false;
}
return createKeyStore(ks); return createKeyStore(ks);
} }
@ -697,31 +690,13 @@ public class RouterConsoleRunner implements RouterApp {
*/ */
private boolean createKeyStore(File ks) { private boolean createKeyStore(File ks) {
// make a random 48 character password (30 * 8 / 5) // make a random 48 character password (30 * 8 / 5)
byte[] rand = new byte[30]; String keyPassword = KeyStoreUtil.randomString();
_context.random().nextBytes(rand);
String keyPassword = Base32.encode(rand);
// and one for the cname // and one for the cname
_context.random().nextBytes(rand); String cname = KeyStoreUtil.randomString() + ".console.i2p.net";
String cname = Base32.encode(rand) + ".console.i2p.net"; boolean success = KeyStoreUtil.createKeys(ks, "console", cname, "Console", keyPassword);
String keytool = (new File(System.getProperty("java.home"), "bin/keytool")).getAbsolutePath();
String[] args = new String[] {
keytool,
"-genkey", // -genkeypair preferred in newer keytools, but this works with more
"-storetype", KeyStore.getDefaultType(),
"-keystore", ks.getAbsolutePath(),
"-storepass", DEFAULT_KEYSTORE_PASSWORD,
"-alias", "console",
"-dname", "CN=" + cname + ",OU=Console,O=I2P Anonymous Network,L=XX,ST=XX,C=XX",
"-validity", "3652", // 10 years
"-keyalg", "DSA",
"-keysize", "1024",
"-keypass", keyPassword};
boolean success = (new ShellCommand()).executeSilentAndWaitTimed(args, 30); // 30 secs
if (success) { if (success) {
success = ks.exists(); success = ks.exists();
if (success) { if (success) {
SecureFileOutputStream.setPerms(ks);
try { try {
Map<String, String> changes = new HashMap(); Map<String, String> changes = new HashMap();
changes.put(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD); changes.put(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD);
@ -735,13 +710,8 @@ public class RouterConsoleRunner implements RouterApp {
"The certificate name was generated randomly, and is not associated with your " + "The certificate name was generated randomly, and is not associated with your " +
"IP address, host name, router identity, or destination keys."); "IP address, host name, router identity, or destination keys.");
} else { } else {
System.err.println("Failed to create console SSL keystore using command line:"); System.err.println("Failed to create console SSL keystore.\n" +
StringBuilder buf = new StringBuilder(256); "This is for the Sun/Oracle keytool, others may be incompatible.\n" +
for (int i = 0; i < args.length; i++) {
buf.append('"').append(args[i]).append("\" ");
}
System.err.println(buf.toString());
System.err.println("This is for the Sun/Oracle keytool, others may be incompatible.\n" +
"If you create the keystore manually, you must add " + PROP_KEYSTORE_PASSWORD + " and " + PROP_KEY_PASSWORD + "If you create the keystore manually, you must add " + PROP_KEYSTORE_PASSWORD + " and " + PROP_KEY_PASSWORD +
" to " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath()); " to " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath());
} }

View File

@ -39,7 +39,7 @@ public class TunnelRenderer {
Map<Hash, TunnelPool> clientInboundPools = _context.tunnelManager().getInboundClientPools(); Map<Hash, TunnelPool> clientInboundPools = _context.tunnelManager().getInboundClientPools();
Map<Hash, TunnelPool> clientOutboundPools = _context.tunnelManager().getOutboundClientPools(); Map<Hash, TunnelPool> clientOutboundPools = _context.tunnelManager().getOutboundClientPools();
destinations = new ArrayList(clientInboundPools.keySet()); destinations = new ArrayList(clientInboundPools.keySet());
boolean debug = _context.getBooleanProperty(ConfigTunnelsHelper.PROP_ADVANCED); boolean debug = _context.getBooleanProperty(HelperBase.PROP_ADVANCED);
for (int i = 0; i < destinations.size(); i++) { for (int i = 0; i < destinations.size(); i++) {
Hash client = destinations.get(i); Hash client = destinations.get(i);
boolean isLocal = _context.clientManager().isLocal(client); boolean isLocal = _context.clientManager().isLocal(client);

View File

@ -66,6 +66,8 @@ public class UpdateHandler {
_nonce.equals(System.getProperty("net.i2p.router.web.UpdateHandler.noncePrev"))) { _nonce.equals(System.getProperty("net.i2p.router.web.UpdateHandler.noncePrev"))) {
if (_action.contains("Unsigned")) { if (_action.contains("Unsigned")) {
update(ROUTER_UNSIGNED); update(ROUTER_UNSIGNED);
} else if (ConfigUpdateHandler.USE_SU3_UPDATE) {
update(ROUTER_SIGNED_SU3);
} else { } else {
update(ROUTER_SIGNED); update(ROUTER_SIGNED);
} }
@ -76,7 +78,8 @@ public class UpdateHandler {
ConsoleUpdateManager mgr = (ConsoleUpdateManager) _context.updateManager(); ConsoleUpdateManager mgr = (ConsoleUpdateManager) _context.updateManager();
if (mgr == null) if (mgr == null)
return; return;
if (mgr.isUpdateInProgress(ROUTER_SIGNED) || mgr.isUpdateInProgress(ROUTER_UNSIGNED)) { if (mgr.isUpdateInProgress(ROUTER_SIGNED) || mgr.isUpdateInProgress(ROUTER_UNSIGNED) ||
mgr.isUpdateInProgress(ROUTER_SIGNED_SU3)) {
_log.error("Update already running"); _log.error("Update already running");
return; return;
} }

View File

@ -48,18 +48,24 @@
<tr><td class="mediumtags" align="right"><b><%=formhandler._("Update policy")%>:</b></td> <tr><td class="mediumtags" align="right"><b><%=formhandler._("Update policy")%>:</b></td>
<td><jsp:getProperty name="updatehelper" property="updatePolicySelectBox" /></td></tr> <td><jsp:getProperty name="updatehelper" property="updatePolicySelectBox" /></td></tr>
<% } // if canInstall %> <% } // if canInstall %>
<tr><td class="mediumtags" align="right"><b><%=intl._("Fetch news through the eepProxy?")%></b></td>
<td><jsp:getProperty name="updatehelper" property="newsThroughProxy" /></td></tr>
<tr><td class="mediumtags" align="right"><b><%=intl._("Update through the eepProxy?")%></b></td> <tr><td class="mediumtags" align="right"><b><%=intl._("Update through the eepProxy?")%></b></td>
<td><jsp:getProperty name="updatehelper" property="updateThroughProxy" /></td> <td><jsp:getProperty name="updatehelper" property="updateThroughProxy" /></td></tr>
</tr><tr><td class="mediumtags" align="right"><b><%=intl._("eepProxy host")%>:</b></td> <% if (updatehelper.isAdvanced()) { %>
<tr><td class="mediumtags" align="right"><b><%=intl._("eepProxy host")%>:</b></td>
<td><input type="text" size="10" name="proxyHost" value="<jsp:getProperty name="updatehelper" property="proxyHost" />" /></td> <td><input type="text" size="10" name="proxyHost" value="<jsp:getProperty name="updatehelper" property="proxyHost" />" /></td>
</tr><tr><td class="mediumtags" align="right"><b><%=intl._("eepProxy port")%>:</b></td> </tr><tr><td class="mediumtags" align="right"><b><%=intl._("eepProxy port")%>:</b></td>
<td><input type="text" size="10" name="proxyPort" value="<jsp:getProperty name="updatehelper" property="proxyPort" />" /></td></tr> <td><input type="text" size="10" name="proxyPort" value="<jsp:getProperty name="updatehelper" property="proxyPort" />" /></td></tr>
<% } // if isAdvanced %>
<% if (updatehelper.canInstall()) { %> <% if (updatehelper.canInstall()) { %>
<% if (updatehelper.isAdvanced()) { %>
<tr><td class="mediumtags" align="right"><b><%=intl._("Update URLs")%>:</b></td> <tr><td class="mediumtags" align="right"><b><%=intl._("Update URLs")%>:</b></td>
<td><textarea cols="60" rows="6" name="updateURL" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td> <td><textarea cols="60" rows="6" name="updateURL" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td>
</tr><tr><td class="mediumtags" align="right"><b><%=intl._("Trusted keys")%>:</b></td> </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Trusted keys")%>:</b></td>
<td><textarea cols="60" rows="6" name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td> <td><textarea cols="60" rows="6" name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td></tr>
</tr><tr><td id="unsignedbuild" class="mediumtags" align="right"><b><%=intl._("Update with unsigned development builds?")%></b></td> <% } // if isAdvanced %>
<tr><td id="unsignedbuild" class="mediumtags" align="right"><b><%=intl._("Update with unsigned development builds?")%></b></td>
<td><jsp:getProperty name="updatehelper" property="updateUnsigned" /></td> <td><jsp:getProperty name="updatehelper" property="updateUnsigned" /></td>
</tr><tr><td class="mediumtags" align="right"><b><%=intl._("Unsigned Build URL")%>:</b></td> </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Unsigned Build URL")%>:</b></td>
<td><input type="text" size="60" name="zipURL" value="<jsp:getProperty name="updatehelper" property="zipURL" />"></td></tr> <td><input type="text" size="60" name="zipURL" value="<jsp:getProperty name="updatehelper" property="zipURL" />"></td></tr>

View File

@ -0,0 +1,16 @@
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<%@include file="css.jsi" %>
<%=intl.title("Proof")%>
<script src="/js/ajax.js" type="text/javascript"></script>
<%@include file="summaryajax.jsi" %>
</head><body onload="initAjax()">
<%@include file="summary.jsi" %><h1>Proof of Ownership</h1>
<div class="main" id="main">
<jsp:useBean class="net.i2p.router.web.ProofHelper" id="proofHelper" scope="request" />
<jsp:setProperty name="proofHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
<textarea cols="70" rows="15" wrap="off" readonly="readonly" spellcheck="false"><jsp:getProperty name="proofHelper" property="proof" /></textarea>
</div></body></html>

View File

@ -3,13 +3,15 @@
# This file is distributed under the same license as the routerconsole package. # This file is distributed under the same license as the routerconsole package.
# To contribute translations, see http://www.i2p2.de/newdevelopers # To contribute translations, see http://www.i2p2.de/newdevelopers
# #
# Translators:
# Ashoka <martin2p@posteo.de>, 2013
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-07-13 21:46+0000\n" "POT-Creation-Date: 2013-09-20 10:25+0000\n"
"PO-Revision-Date: 2013-05-08 15:06+0000\n" "PO-Revision-Date: 2013-09-16 07:09+0000\n"
"Last-Translator: zeroflag <zeroflag@i2pmail.org>\n" "Last-Translator: Ashoka <martin2p@posteo.de>\n"
"Language-Team: German (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: German (http://www.transifex.com/projects/p/I2P/language/"
"de/)\n" "de/)\n"
"Language: de\n" "Language: de\n"
@ -26,39 +28,51 @@ msgstr "Willkommen im I2P!"
#, java-format #, java-format
msgid "Please {0}have patience{1} as I2P boots up and finds peers." msgid "Please {0}have patience{1} as I2P boots up and finds peers."
msgstr "Hab noch {0}etwas Geduld{1}, w&auml;hrend I2P startet und weitere I2P-Router findet." msgstr ""
"Hab noch {0}etwas Geduld{1}, w&auml;hrend I2P startet und weitere I2P-Router "
"findet."
#, java-format #, java-format
msgid "" msgid ""
"While you are waiting, please {0}adjust your bandwidth settings{1} on the {2}" "While you are waiting, please {0}adjust your bandwidth settings{1} on the {2}"
"configuration page{3}." "configuration page{3}."
msgstr "Passe bitte in der Zwischenzeit {0}deine Einstellungen zur Bandbreite{1} auf der" msgstr ""
"{2}Einstellungsseite{3} an!" "Passe bitte in der Zwischenzeit {0}deine Einstellungen zur Bandbreite{1} auf "
"der{2}Einstellungsseite{3} an!"
msgid "Also you can setup your browser to use the I2P proxy to reach eepsites." msgid "Also you can setup your browser to use the I2P proxy to reach eepsites."
msgstr "Auch kannst Du gleich deinen Browser f&uuml;r die Nutzung von I2P einrichten." msgstr ""
"Auch kannst Du gleich deinen Browser f&uuml;r die Nutzung von I2P einrichten."
msgid "" msgid ""
"Just enter 127.0.0.1 (or localhost) port 4444 as a http proxy into your " "Just enter 127.0.0.1 (or localhost) port 4444 as a http proxy into your "
"browser settings." "browser settings."
msgstr "Setze in den Einstellungen zum Browser ein HTTP Proxy ein mit 127.0.0.1 (oder localhost) mit Port 4444 als Ziel." msgstr ""
"Setze in den Einstellungen zum Browser ein HTTP Proxy ein mit 127.0.0.1 "
"(oder localhost) mit Port 4444 als Ziel."
msgid "Do not use SOCKS for this." msgid "Do not use SOCKS for this."
msgstr "" msgstr "Benutze keine SOCKS dafür."
#, java-format #, java-format
msgid "" msgid ""
"More information can be found on the {0}I2P browser proxy setup page{1}." "More information can be found on the {0}I2P browser proxy setup page{1}."
msgstr "Mehr Informationen gibt es auf der {0}I2P browser proxy Setup Seite{1}." msgstr ""
"Mehr Informationen gibt es auf der {0}I2P browser proxy Setup Seite{1}."
#, java-format #, java-format
msgid "" msgid ""
"Once you have a \"shared clients\" destination listed on the left, please {0}" "Once you have a \"shared clients\" destination listed on the left, please {0}"
"check out{1} our {2}FAQ{3}." "check out{1} our {2}FAQ{3}."
msgstr "Sobald auf der linken Seite eine Verbindung namens \"versch. Klienten\" aufgelistet ist, kannst Du unsere {0}{1} {2}FAQ{3} besuchen." msgstr ""
"Sobald auf der linken Seite eine Verbindung namens \"versch. Klienten\" "
"aufgelistet ist, kannst Du unsere {0}{1} {2}FAQ{3} besuchen."
#, java-format #, java-format
msgid "" msgid ""
"Point your IRC client to {0}localhost:6668{1} and say hi to us on {2}#i2p-" "Point your IRC client to {0}localhost:6668{1} and say hi to us on {2}#i2p-"
"help{3} or {4}#i2p{5}." "help{3} or {4}#i2p{5}."
msgstr "Verbinde deinen IRC-Klienten mit dem Server auf {0}localhost:6668{1} und schau bei uns im Kanal <a href=\"irc://127.0.0.1:6668/i2p-de\">#i2p-de</a>, {2}#i2p-help{3} oder {4}#i2p{5} vorbei!" msgstr ""
"Verbinde deinen IRC-Klienten mit dem Server auf {0}localhost:6668{1} und "
"schau bei uns im Kanal <a href=\"irc://127.0.0.1:6668/i2p-de\">#i2p-de</a>, "
"{2}#i2p-help{3} oder {4}#i2p{5} vorbei!"

View File

@ -4,15 +4,16 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers # To contribute translations, see http://www.i2p2.de/newdevelopers
# #
# Translators: # Translators:
# Boxoa590, 2013
# foo <foo@bar>, 2009 # foo <foo@bar>, 2009
# Boxoa590, 2013 # Boxoa590, 2013
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-11 15:43+0000\n" "POT-Creation-Date: 2013-09-20 10:24+0000\n"
"PO-Revision-Date: 2013-07-22 20:37+0000\n" "PO-Revision-Date: 2013-08-11 15:50+0000\n"
"Last-Translator: Boxoa590\n" "Last-Translator: kytv <killyourtv@i2pmail.org>\n"
"Language-Team: French (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: French (http://www.transifex.com/projects/p/I2P/language/"
"fr/)\n" "fr/)\n"
"Language: fr\n" "Language: fr\n"

View File

@ -3,13 +3,16 @@
# This file is distributed under the same license as the routerconsole package. # This file is distributed under the same license as the routerconsole package.
# To contribute translations, see http://www.i2p2.de/newdevelopers # To contribute translations, see http://www.i2p2.de/newdevelopers
# #
# Translators:
# hottuna <i2p@robertfoss.se>, 2013
# hottuna <i2p@robertfoss.se>, 2013
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-07-13 21:46+0000\n" "POT-Creation-Date: 2013-09-26 21:42+0000\n"
"PO-Revision-Date: 2013-01-03 09:01+0000\n" "PO-Revision-Date: 2013-09-26 06:40+0000\n"
"Last-Translator: mon <mattias.ohlsson@inprose.com>\n" "Last-Translator: hottuna <i2p@robertfoss.se>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/" "Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/"
"language/sv_SE/)\n" "language/sv_SE/)\n"
"Language: sv_SE\n" "Language: sv_SE\n"
@ -19,7 +22,7 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Congratulations on getting I2P installed!" msgid "Congratulations on getting I2P installed!"
msgstr "" msgstr "Grattis för din I2P installation!"
msgid "Welcome to I2P!" msgid "Welcome to I2P!"
msgstr "Välkommen till I2P!" msgstr "Välkommen till I2P!"
@ -32,32 +35,43 @@ msgstr "{0}Ha tålamod{1} medan I2P startar upp och letar upp peers."
msgid "" msgid ""
"While you are waiting, please {0}adjust your bandwidth settings{1} on the {2}" "While you are waiting, please {0}adjust your bandwidth settings{1} on the {2}"
"configuration page{3}." "configuration page{3}."
msgstr "Medan du väntar, var god {0}ställ in dina bandbreddd och port inställningar{1} på {2}konfigurations-sidan{3}." msgstr ""
"Medan du väntar, var god {0}ställ in dina bandbreddd och port "
"inställningar{1} på {2}konfigurations-sidan{3}."
msgid "Also you can setup your browser to use the I2P proxy to reach eepsites." msgid "Also you can setup your browser to use the I2P proxy to reach eepsites."
msgstr "" msgstr ""
"Du kan även ställa in din webbläsare till att använda I2P-proxyn för att nå "
"eepsidor."
msgid "" msgid ""
"Just enter 127.0.0.1 (or localhost) port 4444 as a http proxy into your " "Just enter 127.0.0.1 (or localhost) port 4444 as a http proxy into your "
"browser settings." "browser settings."
msgstr "" msgstr ""
"Skriv in 127.0.0.1 (eller localhost) port 4444 som en http-proxy i din "
"webbläsares inställningar."
msgid "Do not use SOCKS for this." msgid "Do not use SOCKS for this."
msgstr "" msgstr "Använd inte SOCKS för detta."
#, java-format #, java-format
msgid "" msgid ""
"More information can be found on the {0}I2P browser proxy setup page{1}." "More information can be found on the {0}I2P browser proxy setup page{1}."
msgstr "" msgstr ""
"Mer information kan hittsa på {0}I2P webbläsar-proxy inställnings sidan{1}."
#, java-format #, java-format
msgid "" msgid ""
"Once you have a \"shared clients\" destination listed on the left, please {0}" "Once you have a \"shared clients\" destination listed on the left, please {0}"
"check out{1} our {2}FAQ{3}." "check out{1} our {2}FAQ{3}."
msgstr "När du har en \"delade klienter\" distination listad på vänster sida, {0}kika på{1} vår {2}FAQ{3}." msgstr ""
"När du har en \"delade klienter\" distination listad på vänster sida, {0}"
"kika på{1} vår {2}FAQ{3}."
#, java-format #, java-format
msgid "" msgid ""
"Point your IRC client to {0}localhost:6668{1} and say hi to us on {2}#i2p-" "Point your IRC client to {0}localhost:6668{1} and say hi to us on {2}#i2p-"
"help{3} or {4}#i2p{5}." "help{3} or {4}#i2p{5}."
msgstr "Rikta din IRC-klient till {0}localhost:6668{1} och säg hej till oss på {2}#i2p-help{3} eller {4}#i2p{5}." msgstr ""
"Rikta din IRC-klient till {0}localhost:6668{1} och säg hej till oss på {2}"
"#i2p-help{3} eller {4}#i2p{5}."

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -204,7 +204,7 @@ public class I2PSocketManagerFull implements I2PSocketManager {
private void verifySession() throws I2PException { private void verifySession() throws I2PException {
if (_isDestroyed.get()) if (_isDestroyed.get())
throw new I2PException("destroyed"); throw new I2PException("Session was closed");
if (!_connectionManager.getSession().isClosed()) if (!_connectionManager.getSession().isClosed())
return; return;
_connectionManager.getSession().connect(); _connectionManager.getSession().connect();

View File

@ -4,27 +4,29 @@
# To contribute translations, see http://www.i2p2.de/newdevelopers # To contribute translations, see http://www.i2p2.de/newdevelopers
# #
# Translators: # Translators:
# <ducki2p@gmail.com>, 2011. # ducki2p <ducki2p@gmail.com>, 2011
# Martin Svensson <digitalmannen@gmail.com>, 2011, 2012. # hottuna <i2p@robertfoss.se>, 2013
# hottuna <i2p@robertfoss.se>, 2012
# Martin Svensson <digitalmannen@gmail.com>, 2011, 2012
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-04-25 14:51+0000\n" "POT-Creation-Date: 2013-09-26 21:43+0000\n"
"PO-Revision-Date: 2012-07-23 16:33+0000\n" "PO-Revision-Date: 2013-09-26 07:31+0000\n"
"Last-Translator: Martin Svensson <digitalmannen@gmail.com>\n" "Last-Translator: hottuna <i2p@robertfoss.se>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/" "Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/"
"language/sv_SE/)\n" "language/sv_SE/)\n"
"Language: sv_SE\n" "Language: sv_SE\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../src/java/src/i2p/susi/dns/AddressBean.java:130 #: ../src/java/src/i2p/susi/dns/AddressBean.java:130
#, java-format #, java-format
msgid "Host name \"{0}\" contains illegal character {1}" msgid "Host name \"{0}\" contains illegal character {1}"
msgstr " Värdnamn \"{0}\" innehåller ogiltigttecken {1}" msgstr " Värdnamn \"{0}\" innehåller ogiltiga tecken {1}"
#: ../src/java/src/i2p/susi/dns/AddressBean.java:143 #: ../src/java/src/i2p/susi/dns/AddressBean.java:143
#: ../src/java/src/i2p/susi/dns/AddressBean.java:145 #: ../src/java/src/i2p/susi/dns/AddressBean.java:145
@ -55,7 +57,7 @@ msgstr ""
#: ../src/java/src/i2p/susi/dns/AddressBean.java:218 #: ../src/java/src/i2p/susi/dns/AddressBean.java:218
msgid "None" msgid "None"
msgstr "Ingen" msgstr "Inga"
#: ../src/java/src/i2p/susi/dns/AddressBean.java:226 #: ../src/java/src/i2p/susi/dns/AddressBean.java:226
msgid "Hashcash" msgid "Hashcash"
@ -63,7 +65,7 @@ msgstr "Hashcash"
#: ../src/java/src/i2p/susi/dns/AddressBean.java:228 #: ../src/java/src/i2p/susi/dns/AddressBean.java:228
msgid "Hidden" msgid "Hidden"
msgstr "Dold" msgstr "Gömd"
#: ../src/java/src/i2p/susi/dns/AddressBean.java:230 #: ../src/java/src/i2p/susi/dns/AddressBean.java:230
msgid "Signed" msgid "Signed"
@ -79,7 +81,7 @@ msgstr "Typ {0}"
msgid "One result for search within filtered list." msgid "One result for search within filtered list."
msgid_plural "{0} results for search within filtered list." msgid_plural "{0} results for search within filtered list."
msgstr[0] "Ett resultat för sökning i filtrerlistan." msgstr[0] "Ett resultat för sökning i filtrerlistan."
msgstr[1] "{0} resultat för sökning i filtrerlistan ." msgstr[1] "{0} resultat för sökning i filtrerlistan."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:206 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:206
#, java-format #, java-format
@ -93,7 +95,7 @@ msgstr[1] "Filtrerlistan innehåller {0} poster."
msgid "One result for search." msgid "One result for search."
msgid_plural "{0} results for search." msgid_plural "{0} results for search."
msgstr[0] "Ett resultat på sökningen." msgstr[0] "Ett resultat på sökningen."
msgstr[1] "{0} resultat sökningen." msgstr[1] "{0} resultat till sökningen."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:220 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:220
#, java-format #, java-format
@ -141,13 +143,13 @@ msgstr ""
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:253 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:253
#, java-format #, java-format
msgid "Destination added for {0}." msgid "Destination added for {0}."
msgstr "Mål till lagt för {0}." msgstr "Mål tillagt för {0}."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:285 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:285
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:255 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:255
#, java-format #, java-format
msgid "Destination changed for {0}." msgid "Destination changed for {0}."
msgstr "Målet ändrat för {0}." msgstr "Mål ändrat för {0}."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:287 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:287
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:257 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:257
@ -157,7 +159,7 @@ msgstr "Varning - värdnamn slutar inte med \".i2p\""
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:292 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:292
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:265 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:265
msgid "Invalid Base 64 destination." msgid "Invalid Base 64 destination."
msgstr "Ogiltigt Base 64 mål" msgstr "Ogiltigt Base64 mål."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:298 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:298
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:271 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:271
@ -168,7 +170,7 @@ msgstr "Ogiltigt värdnamn \"{0}\"."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:301 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:301
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:274 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:274
msgid "Please enter a host name and destination" msgid "Please enter a host name and destination"
msgstr "Ange värdnamn och destination" msgstr "Ange värdnamn och mål"
#. clear search when deleting #. clear search when deleting
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:305 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:305
@ -183,14 +185,14 @@ msgstr "Ta bort post"
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:278 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:278
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:349 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:349
msgid "Delete Selected" msgid "Delete Selected"
msgstr "Radera valda" msgstr "Radera Valda"
#. parameter is a host name #. parameter is a host name
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:319 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:319
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:295 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:295
#, java-format #, java-format
msgid "Destination {0} deleted." msgid "Destination {0} deleted."
msgstr "mål {0} raderat." msgstr "Mål {0} raderat."
#. parameter will always be >= 2 #. parameter will always be >= 2
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:322 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:322
@ -204,7 +206,7 @@ msgstr[1] "{0} mål raderade."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:324 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:324
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:300 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:300
msgid "No entries selected to delete." msgid "No entries selected to delete."
msgstr "Inga uppgifter valda för radering." msgstr "Inga poster valda för radering."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:332 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:332
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:307 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:307
@ -216,46 +218,47 @@ msgid "ERROR: Could not write addressbook file."
msgstr "FEL: Kunde inte skriva till adressboks filen." msgstr "FEL: Kunde inte skriva till adressboks filen."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:340 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:340
#: ../src/java/src/i2p/susi/dns/ConfigBean.java:149 #: ../src/java/src/i2p/susi/dns/ConfigBean.java:140
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:311 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:311
#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:128 #: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:142
msgid "" msgid ""
"Invalid form submission, probably because you used the \"back\" or \"reload" "Invalid form submission, probably because you used the \"back\" or \"reload"
"\" button on your browser. Please resubmit." "\" button on your browser. Please resubmit."
msgstr "" msgstr ""
"Felaktigt formulär, förmodligen för att du använde \"Bakåt \" eller " "Felaktigt formulär skickat, förmodligen för att du använde \"Bakåt \" eller "
"\"Uppdaterings\" knappen i din webbläsare. Försök skicka igen." "\"Ladda Om\" knappen i din webbläsare. Försök skicka igen."
#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:342 #: ../src/java/src/i2p/susi/dns/AddressbookBean.java:342
#: ../src/java/src/i2p/susi/dns/ConfigBean.java:151 #: ../src/java/src/i2p/susi/dns/ConfigBean.java:142
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:313 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:313
#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:130 #: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:144
msgid "" msgid ""
"If the problem persists, verify that you have cookies enabled in your " "If the problem persists, verify that you have cookies enabled in your "
"browser." "browser."
msgstr "" msgstr ""
"Om problemet kvarstår, bekräfta att du har cookies påslaget i din browser."
#: ../src/java/src/i2p/susi/dns/ConfigBean.java:140 #: ../src/java/src/i2p/susi/dns/ConfigBean.java:131
#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:103 #: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:117
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:153 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:153
#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:145 #: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:145
msgid "Save" msgid "Save"
msgstr "Spara" msgstr "Spara"
#: ../src/java/src/i2p/susi/dns/ConfigBean.java:142 #: ../src/java/src/i2p/susi/dns/ConfigBean.java:133
msgid "Configuration saved." msgid "Configuration saved."
msgstr "Inställningarna sparas." msgstr "Inställningar sparade."
#: ../src/java/src/i2p/susi/dns/ConfigBean.java:143 #: ../src/java/src/i2p/susi/dns/ConfigBean.java:134
#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:122 #: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:136
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:151 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:151
#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:143 #: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:143
msgid "Reload" msgid "Reload"
msgstr "Ladda om" msgstr "Ladda om"
#: ../src/java/src/i2p/susi/dns/ConfigBean.java:145 #: ../src/java/src/i2p/susi/dns/ConfigBean.java:136
msgid "Configuration reloaded." msgid "Configuration reloaded."
msgstr "Konfiguration laddas om." msgstr "Inställningar laddade igen."
#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:100 #: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:100
#, java-format #, java-format
@ -276,23 +279,24 @@ msgstr "Kunde inte lägga till målet för {0} till namntjänsten {1}"
msgid "Failed to delete Destination for {0} from naming service {1}" msgid "Failed to delete Destination for {0} from naming service {1}"
msgstr "Det gick inte att ta bort målet för {0} från namntjänsten {1}" msgstr "Det gick inte att ta bort målet för {0} från namntjänsten {1}"
#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:115 #: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:129
msgid "" msgid ""
"Subscriptions saved, updating addressbook from subscription sources now." "Subscriptions saved, updating addressbook from subscription sources now."
msgstr "" msgstr ""
"Abonnemang sparade, uppdatering adressbok från abonnemangs källorna nu." "Prenumerationer sparade, uppdaterar adressbok från prenumerations-källorna "
"nu."
#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:120 #: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:134
msgid "Subscriptions saved." msgid "Subscriptions saved."
msgstr "Abonnemang sprade" msgstr "Prenumerationer sparade."
#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:124 #: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:138
msgid "Subscriptions reloaded." msgid "Subscriptions reloaded."
msgstr "Abonnemang laddas om." msgstr "Prenumerationer laddade igen."
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:125 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:125
msgid "address book" msgid "address book"
msgstr "adressboken" msgstr "adressbok"
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:131 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:131
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:147 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:147
@ -352,7 +356,7 @@ msgstr "publicerad"
#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:126 #: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:126
#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:129 #: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:129
msgid "Subscriptions" msgid "Subscriptions"
msgstr "Abonnemang" msgstr "Prenumerationer"
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:145 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:145
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:139 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:139
@ -413,11 +417,11 @@ msgstr "Mål"
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:286 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:286
msgid "Mark for deletion" msgid "Mark for deletion"
msgstr "Markera för att raderas" msgstr "Markera för borttagning"
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:305 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:305
msgid "Base 32 address" msgid "Base 32 address"
msgstr "Base 32 adress" msgstr "Base32 adress"
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:309 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:309
msgid "More information on this entry" msgid "More information on this entry"
@ -434,7 +438,7 @@ msgstr "Avbryt"
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:381 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:381
msgid "This address book is empty." msgid "This address book is empty."
msgstr "Denna adressbok är tom" msgstr "Denna adressboken är tom."
#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:396 #: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:396
msgid "Add new destination" msgid "Add new destination"
@ -447,7 +451,7 @@ msgstr "Värdnamn"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:119 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:119
msgid "configuration" msgid "configuration"
msgstr "konfiguration" msgstr "inställningar"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:155 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:155
msgid "Hints" msgid "Hints"
@ -459,7 +463,7 @@ msgid ""
"directory, which is normally ~/.i2p/addressbook/ (Linux) or %APPDATA%\\I2P" "directory, which is normally ~/.i2p/addressbook/ (Linux) or %APPDATA%\\I2P"
"\\addressbook\\ (Windows)." "\\addressbook\\ (Windows)."
msgstr "" msgstr ""
"Fil och katalog sökvägar anges här i förhållande till adressboken " "Fil och katalog sökvägar anges här i förhållande till adressbokens "
"arbetskatalog, som normalt är ~/.i2p/addressbook/ (Linux) eller %APPDATA%" "arbetskatalog, som normalt är ~/.i2p/addressbook/ (Linux) eller %APPDATA%"
"\\I2P\\addressbook\\ (Windows)." "\\I2P\\addressbook\\ (Windows)."
@ -484,15 +488,14 @@ msgid ""
"When you publish your addressbook, ALL destinations from the master and " "When you publish your addressbook, ALL destinations from the master and "
"router addressbooks appear there." "router addressbooks appear there."
msgstr "" msgstr ""
"När du publicerar din adressbok, Kommer samtliga destinationer från master " "När du publicerar din adressbok, kommer samtliga destinationer från master "
"och routerns adressböcker visas där." "och routerns adressböcker visas där."
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:163 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:163
msgid "" msgid ""
"Use the private addressbook for private destinations, these are not " "Use the private addressbook for private destinations, these are not "
"published." "published."
msgstr "" msgstr "Använd den privata adressboken för privata mål, dessa publiceras inte."
"Använd privata adressboken för privata mål, dessa inte publiceras inte."
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:165 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:165
msgid "Options" msgid "Options"
@ -501,8 +504,8 @@ msgstr "Alternativ"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:167 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:167
msgid "File containing the list of subscriptions URLs (no need to change)" msgid "File containing the list of subscriptions URLs (no need to change)"
msgstr "" msgstr ""
"Fil som innehåller en förteckning över prenumerations URLer (ingen anledning " "Fil som innehåller en lista över prenumerations URLer (ingen anledning att "
"att ändra)" "ändra)"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:169 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:169
msgid "Update interval in hours" msgid "Update interval in hours"
@ -513,11 +516,11 @@ msgid ""
"Your public hosts.txt file (choose a path within your webserver document " "Your public hosts.txt file (choose a path within your webserver document "
"root)" "root)"
msgstr "" msgstr ""
"Din publika hosts.txt fil (välj en sökväg till din webbservers dokumentrot)" "Din publika hosts.txt fil (välj en sökväg till din webbservers dokumentrot)"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:173 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:173
msgid "Your hosts.txt (don't change)" msgid "Your hosts.txt (don't change)"
msgstr "Din hosts.tx (ändra inte)" msgstr "Din hosts.txt (ändra inte)"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:175 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:175
msgid "Your personal addressbook, these hosts will be published" msgid "Your personal addressbook, these hosts will be published"
@ -529,11 +532,11 @@ msgstr "Din privata adressbok, den publiceras aldrig"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:179 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:179
msgid "Port for your eepProxy (no need to change)" msgid "Port for your eepProxy (no need to change)"
msgstr "Port för din eepProxy (du behöver inte ändra)" msgstr "Port för din eepProxy (den behöver inte ändras)"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:181 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:181
msgid "Hostname for your eepProxy (no need to change)" msgid "Hostname for your eepProxy (no need to change)"
msgstr "Värd namn fär din eepProxy (du behöver inte ändra)" msgstr "Värdnamn för din eepProxy (den behöver inte ändras)"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:183 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:183
msgid "Whether to update the published addressbook" msgid "Whether to update the published addressbook"
@ -544,20 +547,20 @@ msgid ""
"File containing the etags header from the fetched subscription URLs (no need " "File containing the etags header from the fetched subscription URLs (no need "
"to change)" "to change)"
msgstr "" msgstr ""
"Fil som innehåller etags header från hämtade prenumeration URLer (du behöver " "Fil som innehåller etags header från hämtade prenumeration URL:er (den "
"inte ändra)" "behöver inte ändras)"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:187 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:187
msgid "" msgid ""
"File containing the modification timestamp for each fetched subscription URL " "File containing the modification timestamp for each fetched subscription URL "
"(no need to change)" "(no need to change)"
msgstr "" msgstr ""
"Fil som innehåller en ändring tidsstämpeln för varje hämtade prenumeration " "Fil som innehåller en ändring-tidsstämpeln för varje hämtad prenumerations "
"URL (behävs inte ändras)" "URL (den behöver inte ändras)"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:189 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:189
msgid "File to log activity to (change to /dev/null if you like)" msgid "File to log activity to (change to /dev/null if you like)"
msgstr "Fil loggaktivitet sparas till (ändra till / dev / null om du vill)" msgstr "Fil där loggaktivitet sparas till (ändra till / dev / null om du vill)"
#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:191 #: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:191
msgid "Name of the theme to use (defaults to 'light')" msgid "Name of the theme to use (defaults to 'light')"
@ -569,19 +572,19 @@ msgstr "adressbok"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:179 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:179
msgid "Encoded Name" msgid "Encoded Name"
msgstr "Kodat namn" msgstr "Kodat Namn"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:193 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:193
msgid "Base 32 Address" msgid "Base 32 Address"
msgstr "Base 32 Adress" msgstr "Base32 Adress"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:201 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:201
msgid "Base 64 Hash" msgid "Base 64 Hash"
msgstr "Bas 64 Hash" msgstr "Base64 Hash"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:207 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:207
msgid "Address Helper" msgid "Address Helper"
msgstr "Adress hjälp" msgstr "Adresshjälpare"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:213 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:213
msgid "link" msgid "link"
@ -589,7 +592,7 @@ msgstr "länk"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:217 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:217
msgid "Public Key" msgid "Public Key"
msgstr "Publik nyckel" msgstr "Publik Nyckel"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:219 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:219
msgid "ElGamal 2048 bit" msgid "ElGamal 2048 bit"
@ -609,7 +612,7 @@ msgstr "Certifikat"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:235 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:235
msgid "Added Date" msgid "Added Date"
msgstr "Datum för tillagd" msgstr "Datum för tillägning"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:241 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:241
msgid "Source" msgid "Source"
@ -617,7 +620,7 @@ msgstr "Källa"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:247 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:247
msgid "Last Modified" msgid "Last Modified"
msgstr "Senast modifierad" msgstr "Senast Ändrad"
#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:253 #: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:253
msgid "Notes" msgid "Notes"
@ -625,7 +628,7 @@ msgstr "Anteckningar"
#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:110 #: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:110
msgid "Introduction" msgid "Introduction"
msgstr "Inledning" msgstr "Introduktion"
#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:132 #: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:132
msgid "What is the addressbook?" msgid "What is the addressbook?"
@ -640,8 +643,8 @@ msgid ""
"It regularly updates your hosts.txt file from distributed sources or " "It regularly updates your hosts.txt file from distributed sources or "
"\"subscriptions\"." "\"subscriptions\"."
msgstr "" msgstr ""
"Den uppdaterar din regelbundet hosts.txt fil från distribuerade källor eller " "Den uppdaterar din hosts.txt fil från distribuerade källor eller "
"\"subscriptions\"." "\"prenumerationer\"."
#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:137 #: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:137
msgid "" msgid ""
@ -659,7 +662,6 @@ msgstr ""
"href=\"subscriptions\">subscriptions</a> fil. " "href=\"subscriptions\">subscriptions</a> fil. "
#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:140 #: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:140
#, fuzzy
msgid "" msgid ""
"For more information on naming in I2P, see <a href=\"http://www.i2p2.i2p/" "For more information on naming in I2P, see <a href=\"http://www.i2p2.i2p/"
"naming.html\" target=\"_top\">the overview on www.i2p2.i2p</a>." "naming.html\" target=\"_top\">the overview on www.i2p2.i2p</a>."
@ -690,24 +692,24 @@ msgid ""
"If configured, the router address book is now written to the \"published\" " "If configured, the router address book is now written to the \"published\" "
"address book, which will be publicly available if you are running an eepsite." "address book, which will be publicly available if you are running an eepsite."
msgstr "" msgstr ""
"Om konfigurerad så skrivit router adressboken till \"published\" " "Om konfigurerad så skrivs router adressboken till \"published\" adressboken, "
"adressboken, som är tillgänglig om du kör en eepsite." "som är tillgänglig om du kör en eepsite."
#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:148 #: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:148
msgid "" msgid ""
"The router also uses a private address book (not shown in the picture), " "The router also uses a private address book (not shown in the picture), "
"which is not merged or published." "which is not merged or published."
msgstr "" msgstr ""
"Routern använder också den privat adressbok (syns ej på bilden) som inte är " "Routern använder också en privat adressbok (syns ej på bilden) som inte är "
"samman kopplade eller publicerad." "sammansalgen eller publicerad."
#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:149 #: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:149
msgid "" msgid ""
"Hosts in the private address book can be accessed by you but their addresses " "Hosts in the private address book can be accessed by you but their addresses "
"are never distributed to others." "are never distributed to others."
msgstr "" msgstr ""
"Värdar i den privata adressboken kan nås av dig, men adresserna delas " "Värdar i den privata adressboken kan nås av dig, men adresserna delas aldrig "
"aldrig ut till andra." "ut till andra."
#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:150 #: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:150
msgid "" msgid ""
@ -719,11 +721,11 @@ msgstr ""
#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:111 #: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:111
msgid "subscriptions" msgid "subscriptions"
msgstr "abonnemang" msgstr "prenumerationer"
#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:147 #: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:147
msgid "The subscription file contains a list of i2p URLs." msgid "The subscription file contains a list of i2p URLs."
msgstr "Abonnemangs filen innehåller lista över I2P webbadresser." msgstr "Prenumerations-filen innehåller en lista av I2P URL:er."
#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:148 #: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:148
msgid "" msgid ""
@ -739,7 +741,8 @@ msgid ""
"The default subscription is the hosts.txt from www.i2p2.i2p, which is " "The default subscription is the hosts.txt from www.i2p2.i2p, which is "
"updated infrequently." "updated infrequently."
msgstr "" msgstr ""
"Den förvalda prenumeration är hosts.txt från www.i2p2.i2p uppdateras sällan." "Den förvalda prenumeration är hosts.txt från www.i2p2.i2p, som uppdateras "
"sällan."
#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:151 #: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:151
msgid "" msgid ""

View File

@ -126,6 +126,7 @@
<!-- Update the messages_*.po files. <!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true --> We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" /> <arg value="./bundle-messages.sh" />
</exec> </exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >

View File

@ -15,6 +15,10 @@ TMPFILE=tmp/javafiles.txt
export TZ=UTC export TZ=UTC
RC=0 RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ] if [ "$1" = "-p" ]
then then
POUPDATE=1 POUPDATE=1

View File

@ -80,6 +80,7 @@
<!-- Update the messages_*.po files. <!-- Update the messages_*.po files.
We need to supply the bat file for windows, and then change the fail property to true --> We need to supply the bat file for windows, and then change the fail property to true -->
<exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" failonerror="${require.gettext}" >
<env key="JAVA_HOME" value="${java.home}" />
<arg value="./bundle-messages.sh" /> <arg value="./bundle-messages.sh" />
</exec> </exec>
<exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" > <exec executable="sh" osfamily="mac" failifexecutionfails="true" failonerror="${require.gettext}" >

View File

@ -15,6 +15,10 @@ TMPFILE=javafiles.txt
export TZ=UTC export TZ=UTC
RC=0 RC=0
if ! $(which javac > /dev/null 2>&1); then
export JAVAC=${JAVA_HOME}/../bin/javac
fi
if [ "$1" = "-p" ] if [ "$1" = "-p" ]
then then
POUPDATE=1 POUPDATE=1

View File

@ -14,7 +14,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-08-08 01:26+0000\n" "POT-Creation-Date: 2013-09-20 10:25+0000\n"
"PO-Revision-Date: 2012-08-05 05:57+0000\n" "PO-Revision-Date: 2012-08-05 05:57+0000\n"
"Last-Translator: blabla <blabla@trash-mail.com>\n" "Last-Translator: blabla <blabla@trash-mail.com>\n"
"Language-Team: German (http://www.transifex.com/projects/p/I2P/language/" "Language-Team: German (http://www.transifex.com/projects/p/I2P/language/"
@ -25,428 +25,428 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/src/i2p/susi/webmail/WebMail.java:445 #: src/src/i2p/susi/webmail/WebMail.java:447
msgid "unknown" msgid "unknown"
msgstr "unbekannt" msgstr "unbekannt"
#: src/src/i2p/susi/webmail/WebMail.java:464 #: src/src/i2p/susi/webmail/WebMail.java:466
msgid "Warning: no transfer encoding found, fallback to 7bit." msgid "Warning: no transfer encoding found, fallback to 7bit."
msgstr "Warnung: keine Übertragungskodierung gefunden, Rückgriff auf 7-bit" msgstr "Warnung: keine Übertragungskodierung gefunden, Rückgriff auf 7-bit"
#: src/src/i2p/susi/webmail/WebMail.java:469 #: src/src/i2p/susi/webmail/WebMail.java:471
#, java-format #, java-format
msgid "No encoder found for encoding \\''{0}\\''." msgid "No encoder found for encoding \\''{0}\\''."
msgstr "kein Kodierer für Kodierung \\''{0}\\'' gefunden" msgstr "kein Kodierer für Kodierung \\''{0}\\'' gefunden"
#: src/src/i2p/susi/webmail/WebMail.java:475 #: src/src/i2p/susi/webmail/WebMail.java:477
msgid "Warning: no charset found, fallback to US-ASCII." msgid "Warning: no charset found, fallback to US-ASCII."
msgstr "Warnung: kein Zeichensatz gefunden; Rückgriff auf US-ASCII" msgstr "Warnung: kein Zeichensatz gefunden; Rückgriff auf US-ASCII"
#: src/src/i2p/susi/webmail/WebMail.java:489 #: src/src/i2p/susi/webmail/WebMail.java:491
#, java-format #, java-format
msgid "Charset \\''{0}\\'' not supported." msgid "Charset \\''{0}\\'' not supported."
msgstr "Zeichensatz \\''{0}\\'' nicht unterstützt" msgstr "Zeichensatz \\''{0}\\'' nicht unterstützt"
#: src/src/i2p/susi/webmail/WebMail.java:493 #: src/src/i2p/susi/webmail/WebMail.java:495
#, java-format #, java-format
msgid "Part ({0}) not shown, because of {1}" msgid "Part ({0}) not shown, because of {1}"
msgstr "Teil ({0}) aufgrund von {1} nicht angezeigt" msgstr "Teil ({0}) aufgrund von {1} nicht angezeigt"
#: src/src/i2p/susi/webmail/WebMail.java:516 #: src/src/i2p/susi/webmail/WebMail.java:518
msgid "Download" msgid "Download"
msgstr "Herunterladen" msgstr "Herunterladen"
#: src/src/i2p/susi/webmail/WebMail.java:516 #: src/src/i2p/susi/webmail/WebMail.java:518
msgid "File is packed into a zipfile for security reasons." msgid "File is packed into a zipfile for security reasons."
msgstr "Die Datei wurde aus Sicherheitsgründen in ein Zip-Archiv gepackt." msgstr "Die Datei wurde aus Sicherheitsgründen in ein Zip-Archiv gepackt."
#: src/src/i2p/susi/webmail/WebMail.java:516 #: src/src/i2p/susi/webmail/WebMail.java:518
#, java-format #, java-format
msgid "attachment ({0})." msgid "attachment ({0})."
msgstr "Anhang ({0})." msgstr "Anhang ({0})."
#: src/src/i2p/susi/webmail/WebMail.java:520 #: src/src/i2p/susi/webmail/WebMail.java:522
#, java-format #, java-format
msgid "Attachment ({0})." msgid "Attachment ({0})."
msgstr "Anhang ({0})." msgstr "Anhang ({0})."
#: src/src/i2p/susi/webmail/WebMail.java:570 #: src/src/i2p/susi/webmail/WebMail.java:572
msgid "Need username for authentication." msgid "Need username for authentication."
msgstr "Benutzername zur Authentifizierung benötigt" msgstr "Benutzername zur Authentifizierung benötigt"
#: src/src/i2p/susi/webmail/WebMail.java:574 #: src/src/i2p/susi/webmail/WebMail.java:576
msgid "Need password for authentication." msgid "Need password for authentication."
msgstr "Passwort zur Authentifizierung benötigt" msgstr "Passwort zur Authentifizierung benötigt"
#: src/src/i2p/susi/webmail/WebMail.java:578 #: src/src/i2p/susi/webmail/WebMail.java:580
msgid "Need hostname for connect." msgid "Need hostname for connect."
msgstr "Host-Name für die Verbindung benötigt" msgstr "Host-Name für die Verbindung benötigt"
#: src/src/i2p/susi/webmail/WebMail.java:583 #: src/src/i2p/susi/webmail/WebMail.java:585
msgid "Need port number for pop3 connect." msgid "Need port number for pop3 connect."
msgstr "POP3-Port für die Verbindung benötigt" msgstr "POP3-Port für die Verbindung benötigt"
#: src/src/i2p/susi/webmail/WebMail.java:590 #: src/src/i2p/susi/webmail/WebMail.java:592
msgid "POP3 port number is not in range 0..65535." msgid "POP3 port number is not in range 0..65535."
msgstr "Der POP3-Port liegt nicht im Bereich 0-65535." msgstr "Der POP3-Port liegt nicht im Bereich 0-65535."
#: src/src/i2p/susi/webmail/WebMail.java:596 #: src/src/i2p/susi/webmail/WebMail.java:598
msgid "POP3 port number is invalid." msgid "POP3 port number is invalid."
msgstr "ungültiger POP3-Port" msgstr "ungültiger POP3-Port"
#: src/src/i2p/susi/webmail/WebMail.java:602 #: src/src/i2p/susi/webmail/WebMail.java:604
msgid "Need port number for smtp connect." msgid "Need port number for smtp connect."
msgstr "SMTP-Port für die SMTP-Verbindung benötigt" msgstr "SMTP-Port für die SMTP-Verbindung benötigt"
#: src/src/i2p/susi/webmail/WebMail.java:609 #: src/src/i2p/susi/webmail/WebMail.java:611
msgid "SMTP port number is not in range 0..65535." msgid "SMTP port number is not in range 0..65535."
msgstr "Der SMTP-Port liegt nicht im Bereich 0-65535." msgstr "Der SMTP-Port liegt nicht im Bereich 0-65535."
#: src/src/i2p/susi/webmail/WebMail.java:615 #: src/src/i2p/susi/webmail/WebMail.java:617
msgid "SMTP port number is invalid." msgid "SMTP port number is invalid."
msgstr "ungültiger SMTP-Port" msgstr "ungültiger SMTP-Port"
#: src/src/i2p/susi/webmail/WebMail.java:662 #: src/src/i2p/susi/webmail/WebMail.java:664
msgid "User logged out." msgid "User logged out."
msgstr "Benutzer wurde abgemeldet" msgstr "Benutzer wurde abgemeldet"
#: src/src/i2p/susi/webmail/WebMail.java:666 #: src/src/i2p/susi/webmail/WebMail.java:668
msgid "Internal error, lost connection." msgid "Internal error, lost connection."
msgstr "interner Fehler; Verbindung unterbrochen" msgstr "interner Fehler; Verbindung unterbrochen"
#: src/src/i2p/susi/webmail/WebMail.java:762 #: src/src/i2p/susi/webmail/WebMail.java:764
#, java-format #, java-format
msgid "On {0} {1} wrote:" msgid "On {0} {1} wrote:"
msgstr "Am {0} schrieb {1}:" msgstr "Am {0} schrieb {1}:"
#: src/src/i2p/susi/webmail/WebMail.java:809 #: src/src/i2p/susi/webmail/WebMail.java:811
msgid "begin forwarded mail" msgid "begin forwarded mail"
msgstr "Anfang weitergeleiteter Nachricht" msgstr "Anfang weitergeleiteter Nachricht"
#: src/src/i2p/susi/webmail/WebMail.java:831 #: src/src/i2p/susi/webmail/WebMail.java:833
msgid "end forwarded mail" msgid "end forwarded mail"
msgstr "Ende weitergeleiteter Nachricht" msgstr "Ende weitergeleiteter Nachricht"
#: src/src/i2p/susi/webmail/WebMail.java:838 #: src/src/i2p/susi/webmail/WebMail.java:840
#: src/src/i2p/susi/webmail/WebMail.java:1731 #: src/src/i2p/susi/webmail/WebMail.java:1770
msgid "Could not fetch mail body." msgid "Could not fetch mail body."
msgstr "Konnte den Körper der Nachricht nicht holen." msgstr "Konnte den Körper der Nachricht nicht holen."
#: src/src/i2p/susi/webmail/WebMail.java:866 #: src/src/i2p/susi/webmail/WebMail.java:868
msgid "Message id not valid." msgid "Message id not valid."
msgstr "ungültige Nachrichten-ID" msgstr "ungültige Nachrichten-ID"
#: src/src/i2p/susi/webmail/WebMail.java:949 #: src/src/i2p/susi/webmail/WebMail.java:951
#, java-format #, java-format
msgid "No Encoding found for {0}" msgid "No Encoding found for {0}"
msgstr "keine Kodierung für {0} gefunden" msgstr "keine Kodierung für {0} gefunden"
#: src/src/i2p/susi/webmail/WebMail.java:953 #: src/src/i2p/susi/webmail/WebMail.java:955
#, java-format #, java-format
msgid "Could not encode data: {0}" msgid "Could not encode data: {0}"
msgstr "Konte Daten nicht kodieren: {0}" msgstr "Konte Daten nicht kodieren: {0}"
#: src/src/i2p/susi/webmail/WebMail.java:958 #: src/src/i2p/susi/webmail/WebMail.java:960
#, java-format #, java-format
msgid "Error reading uploaded file: {0}" msgid "Error reading uploaded file: {0}"
msgstr "Fehler beim Lesen der hochzuladenen Datei: {0}" msgstr "Fehler beim Lesen der hochzuladenen Datei: {0}"
#: src/src/i2p/susi/webmail/WebMail.java:1036 #: src/src/i2p/susi/webmail/WebMail.java:1038
msgid "Error parsing download parameter." msgid "Error parsing download parameter."
msgstr "Fehler beim Parsen des Download-Parameters" msgstr "Fehler beim Parsen des Download-Parameters"
#: src/src/i2p/susi/webmail/WebMail.java:1080 #: src/src/i2p/susi/webmail/WebMail.java:1082
msgid "Invalid pagesize number, resetting to default value." msgid "Invalid pagesize number, resetting to default value."
msgstr "ungültige Seitengröße, wird auf Standardwert zurückgesetzt" msgstr "ungültige Seitengröße, wird auf Standardwert zurückgesetzt"
#: src/src/i2p/susi/webmail/WebMail.java:1104 #: src/src/i2p/susi/webmail/WebMail.java:1106
msgid "No messages marked for deletion." msgid "No messages marked for deletion."
msgstr "Keine Nachrichten zum Löschen markiert" msgstr "Keine Nachrichten zum Löschen markiert"
#: src/src/i2p/susi/webmail/WebMail.java:1124 #: src/src/i2p/susi/webmail/WebMail.java:1126
#, java-format #, java-format
msgid "Error deleting message: {0}" msgid "Error deleting message: {0}"
msgstr "Fehler beim Löschen der Nachricht: {0}" msgstr "Fehler beim Löschen der Nachricht: {0}"
#: src/src/i2p/susi/webmail/WebMail.java:1135 #: src/src/i2p/susi/webmail/WebMail.java:1137
#, java-format #, java-format
msgid "1 message deleted." msgid "1 message deleted."
msgid_plural "{0} messages deleted." msgid_plural "{0} messages deleted."
msgstr[0] "Eine Nachricht gelöscht" msgstr[0] "Eine Nachricht gelöscht"
msgstr[1] "{0} Nachrichten gelöscht" msgstr[1] "{0} Nachrichten gelöscht"
#: src/src/i2p/susi/webmail/WebMail.java:1278 #: src/src/i2p/susi/webmail/WebMail.java:1313
#: src/src/i2p/susi/webmail/WebMail.java:1615 #: src/src/i2p/susi/webmail/WebMail.java:1654
msgid "Login" msgid "Login"
msgstr "Anmelden" msgstr "Anmelden"
#: src/src/i2p/susi/webmail/WebMail.java:1280 #: src/src/i2p/susi/webmail/WebMail.java:1315
#, java-format #, java-format
msgid "1 Message" msgid "1 Message"
msgid_plural "{0} Messages" msgid_plural "{0} Messages"
msgstr[0] "Eine Nachricht" msgstr[0] "Eine Nachricht"
msgstr[1] "{0} Nachrichten" msgstr[1] "{0} Nachrichten"
#: src/src/i2p/susi/webmail/WebMail.java:1282 #: src/src/i2p/susi/webmail/WebMail.java:1317
msgid "Show Message" msgid "Show Message"
msgstr "Nachricht anzeigen" msgstr "Nachricht anzeigen"
#: src/src/i2p/susi/webmail/WebMail.java:1344 #: src/src/i2p/susi/webmail/WebMail.java:1383
#, java-format #, java-format
msgid "Error decoding content: {0}" msgid "Error decoding content: {0}"
msgstr "Fehler beim Dekodieren des Inhalts: {0}" msgstr "Fehler beim Dekodieren des Inhalts: {0}"
#: src/src/i2p/susi/webmail/WebMail.java:1349 #: src/src/i2p/susi/webmail/WebMail.java:1388
msgid "Error decoding content: No encoder found." msgid "Error decoding content: No encoder found."
msgstr "Fehler bei der Dekodierung: kein Kodierer gefunden" msgstr "Fehler bei der Dekodierung: kein Kodierer gefunden"
#: src/src/i2p/susi/webmail/WebMail.java:1396 #: src/src/i2p/susi/webmail/WebMail.java:1435
msgid "no subject" msgid "no subject"
msgstr "kein Betreff" msgstr "kein Betreff"
#: src/src/i2p/susi/webmail/WebMail.java:1413 #: src/src/i2p/susi/webmail/WebMail.java:1452
msgid "Found no valid sender address." msgid "Found no valid sender address."
msgstr "Keine gültige Absenderadresse vorgefunden" msgstr "Keine gültige Absenderadresse vorgefunden"
#: src/src/i2p/susi/webmail/WebMail.java:1419 #: src/src/i2p/susi/webmail/WebMail.java:1458
#, java-format #, java-format
msgid "Found no valid address in \\''{0}\\''." msgid "Found no valid address in \\''{0}\\''."
msgstr "keine gültige Adresse in \\''{0}\\''" msgstr "keine gültige Adresse in \\''{0}\\''"
#: src/src/i2p/susi/webmail/WebMail.java:1438 #: src/src/i2p/susi/webmail/WebMail.java:1477
msgid "No recipients found." msgid "No recipients found."
msgstr "keine Empfänger gefunden" msgstr "keine Empfänger gefunden"
#: src/src/i2p/susi/webmail/WebMail.java:1445 #: src/src/i2p/susi/webmail/WebMail.java:1484
msgid "Quoted printable encoder not available." msgid "Quoted printable encoder not available."
msgstr "Der angegebene druckbare Kodierer ist nicht verfügbar." msgstr "Der angegebene druckbare Kodierer ist nicht verfügbar."
#: src/src/i2p/susi/webmail/WebMail.java:1450 #: src/src/i2p/susi/webmail/WebMail.java:1489
msgid "Header line encoder not available." msgid "Header line encoder not available."
msgstr "Kodierer für die Kopfzeilen nicht verfügbar" msgstr "Kodierer für die Kopfzeilen nicht verfügbar"
#: src/src/i2p/susi/webmail/WebMail.java:1501 #: src/src/i2p/susi/webmail/WebMail.java:1540
msgid "Mail sent." msgid "Mail sent."
msgstr "Mail versandt" msgstr "Mail versandt"
#: src/src/i2p/susi/webmail/WebMail.java:1540 #: src/src/i2p/susi/webmail/WebMail.java:1579
msgid "Send" msgid "Send"
msgstr "Senden" msgstr "Senden"
#: src/src/i2p/susi/webmail/WebMail.java:1541 #: src/src/i2p/susi/webmail/WebMail.java:1580
msgid "Cancel" msgid "Cancel"
msgstr "Abbruch" msgstr "Abbruch"
#: src/src/i2p/susi/webmail/WebMail.java:1542 #: src/src/i2p/susi/webmail/WebMail.java:1581
msgid "Delete Attachment" msgid "Delete Attachment"
msgstr "Anhang löschen" msgstr "Anhang löschen"
#: src/src/i2p/susi/webmail/WebMail.java:1543 #: src/src/i2p/susi/webmail/WebMail.java:1582
#: src/src/i2p/susi/webmail/WebMail.java:1637 #: src/src/i2p/susi/webmail/WebMail.java:1676
#: src/src/i2p/susi/webmail/WebMail.java:1718 #: src/src/i2p/susi/webmail/WebMail.java:1757
msgid "Reload Config" msgid "Reload Config"
msgstr "Einstellungen neu laden" msgstr "Einstellungen neu laden"
#: src/src/i2p/susi/webmail/WebMail.java:1544 #: src/src/i2p/susi/webmail/WebMail.java:1583
#: src/src/i2p/susi/webmail/WebMail.java:1638 #: src/src/i2p/susi/webmail/WebMail.java:1677
#: src/src/i2p/susi/webmail/WebMail.java:1719 #: src/src/i2p/susi/webmail/WebMail.java:1758
msgid "Logout" msgid "Logout"
msgstr "Abmelden" msgstr "Abmelden"
#: src/src/i2p/susi/webmail/WebMail.java:1567 #: src/src/i2p/susi/webmail/WebMail.java:1606
#: src/src/i2p/susi/webmail/WebMail.java:1723 #: src/src/i2p/susi/webmail/WebMail.java:1762
msgid "From:" msgid "From:"
msgstr "Von:" msgstr "Von:"
#: src/src/i2p/susi/webmail/WebMail.java:1568 #: src/src/i2p/susi/webmail/WebMail.java:1607
msgid "To:" msgid "To:"
msgstr "An:" msgstr "An:"
#: src/src/i2p/susi/webmail/WebMail.java:1569 #: src/src/i2p/susi/webmail/WebMail.java:1608
msgid "Cc:" msgid "Cc:"
msgstr "Kopie an:" msgstr "Kopie an:"
#: src/src/i2p/susi/webmail/WebMail.java:1570 #: src/src/i2p/susi/webmail/WebMail.java:1609
msgid "Bcc:" msgid "Bcc:"
msgstr "Blindkopie an:" msgstr "Blindkopie an:"
#: src/src/i2p/susi/webmail/WebMail.java:1571 #: src/src/i2p/susi/webmail/WebMail.java:1610
#: src/src/i2p/susi/webmail/WebMail.java:1725 #: src/src/i2p/susi/webmail/WebMail.java:1764
msgid "Subject:" msgid "Subject:"
msgstr "Betreff:" msgstr "Betreff:"
#: src/src/i2p/susi/webmail/WebMail.java:1572 #: src/src/i2p/susi/webmail/WebMail.java:1611
msgid "Bcc to self" msgid "Bcc to self"
msgstr "Blindkopie zurück?" msgstr "Blindkopie zurück?"
#: src/src/i2p/susi/webmail/WebMail.java:1575 #: src/src/i2p/susi/webmail/WebMail.java:1614
msgid "New Attachment:" msgid "New Attachment:"
msgstr "Neuer Anhang:" msgstr "Neuer Anhang:"
#: src/src/i2p/susi/webmail/WebMail.java:1575 #: src/src/i2p/susi/webmail/WebMail.java:1614
msgid "Upload File" msgid "Upload File"
msgstr "Datei hochladen" msgstr "Datei hochladen"
#: src/src/i2p/susi/webmail/WebMail.java:1581 #: src/src/i2p/susi/webmail/WebMail.java:1620
msgid "Attachments:" msgid "Attachments:"
msgstr "Anhänge:" msgstr "Anhänge:"
#. current postman hq length limits 16/12, new postman version 32/32 #. current postman hq length limits 16/12, new postman version 32/32
#: src/src/i2p/susi/webmail/WebMail.java:1604 #: src/src/i2p/susi/webmail/WebMail.java:1643
msgid "User" msgid "User"
msgstr "Benutzer" msgstr "Benutzer"
#: src/src/i2p/susi/webmail/WebMail.java:1605 #: src/src/i2p/susi/webmail/WebMail.java:1644
msgid "Password" msgid "Password"
msgstr "Passwort" msgstr "Passwort"
#: src/src/i2p/susi/webmail/WebMail.java:1610 #: src/src/i2p/susi/webmail/WebMail.java:1649
msgid "Host" msgid "Host"
msgstr "Host" msgstr "Host"
#: src/src/i2p/susi/webmail/WebMail.java:1611 #: src/src/i2p/susi/webmail/WebMail.java:1650
msgid "POP3-Port" msgid "POP3-Port"
msgstr "POP3-Port" msgstr "POP3-Port"
#: src/src/i2p/susi/webmail/WebMail.java:1612 #: src/src/i2p/susi/webmail/WebMail.java:1651
msgid "SMTP-Port" msgid "SMTP-Port"
msgstr "SMTP-Port" msgstr "SMTP-Port"
#: src/src/i2p/susi/webmail/WebMail.java:1615 #: src/src/i2p/susi/webmail/WebMail.java:1654
msgid "Reset" msgid "Reset"
msgstr "Zurücksetzen" msgstr "Zurücksetzen"
#: src/src/i2p/susi/webmail/WebMail.java:1616 #: src/src/i2p/susi/webmail/WebMail.java:1655
msgid "Learn about I2P mail" msgid "Learn about I2P mail"
msgstr "Erfahre etwas über I2P-Mail" msgstr "Erfahre etwas über I2P-Mail"
#: src/src/i2p/susi/webmail/WebMail.java:1617 #: src/src/i2p/susi/webmail/WebMail.java:1656
msgid "Create Account" msgid "Create Account"
msgstr "Konto anlegen" msgstr "Konto anlegen"
#: src/src/i2p/susi/webmail/WebMail.java:1629 #: src/src/i2p/susi/webmail/WebMail.java:1668
msgid "Really delete the marked messages?" msgid "Really delete the marked messages?"
msgstr "Sollen die markierten Nachrichten wirklich gelöscht werden?" msgstr "Sollen die markierten Nachrichten wirklich gelöscht werden?"
#: src/src/i2p/susi/webmail/WebMail.java:1629 #: src/src/i2p/susi/webmail/WebMail.java:1668
msgid "Yes, really delete them!" msgid "Yes, really delete them!"
msgstr "Ja, löschen" msgstr "Ja, löschen"
#: src/src/i2p/susi/webmail/WebMail.java:1631 #: src/src/i2p/susi/webmail/WebMail.java:1670
#: src/src/i2p/susi/webmail/WebMail.java:1710 #: src/src/i2p/susi/webmail/WebMail.java:1749
msgid "New" msgid "New"
msgstr "Verfassen" msgstr "Verfassen"
#: src/src/i2p/susi/webmail/WebMail.java:1632 #: src/src/i2p/susi/webmail/WebMail.java:1671
#: src/src/i2p/susi/webmail/WebMail.java:1711 #: src/src/i2p/susi/webmail/WebMail.java:1750
msgid "Reply" msgid "Reply"
msgstr "Antworten" msgstr "Antworten"
#: src/src/i2p/susi/webmail/WebMail.java:1633 #: src/src/i2p/susi/webmail/WebMail.java:1672
#: src/src/i2p/susi/webmail/WebMail.java:1712 #: src/src/i2p/susi/webmail/WebMail.java:1751
msgid "Reply All" msgid "Reply All"
msgstr "Allen antworten" msgstr "Allen antworten"
#: src/src/i2p/susi/webmail/WebMail.java:1634 #: src/src/i2p/susi/webmail/WebMail.java:1673
#: src/src/i2p/susi/webmail/WebMail.java:1713 #: src/src/i2p/susi/webmail/WebMail.java:1752
msgid "Forward" msgid "Forward"
msgstr "Weiterleiten" msgstr "Weiterleiten"
#: src/src/i2p/susi/webmail/WebMail.java:1635 #: src/src/i2p/susi/webmail/WebMail.java:1674
#: src/src/i2p/susi/webmail/WebMail.java:1714 #: src/src/i2p/susi/webmail/WebMail.java:1753
msgid "Delete" msgid "Delete"
msgstr "Löschen" msgstr "Löschen"
#: src/src/i2p/susi/webmail/WebMail.java:1636 #: src/src/i2p/susi/webmail/WebMail.java:1675
msgid "Check Mail" msgid "Check Mail"
msgstr "Nachrichten abrufen" msgstr "Nachrichten abrufen"
#: src/src/i2p/susi/webmail/WebMail.java:1640 #: src/src/i2p/susi/webmail/WebMail.java:1679
msgid "Sender" msgid "Sender"
msgstr "Absender" msgstr "Absender"
#: src/src/i2p/susi/webmail/WebMail.java:1641 #: src/src/i2p/susi/webmail/WebMail.java:1680
msgid "Subject" msgid "Subject"
msgstr "Betreff" msgstr "Betreff"
#: src/src/i2p/susi/webmail/WebMail.java:1642 #: src/src/i2p/susi/webmail/WebMail.java:1681
msgid "Date" msgid "Date"
msgstr "Datum" msgstr "Datum"
#: src/src/i2p/susi/webmail/WebMail.java:1643 #: src/src/i2p/susi/webmail/WebMail.java:1682
msgid "Size" msgid "Size"
msgstr "Größe" msgstr "Größe"
#: src/src/i2p/susi/webmail/WebMail.java:1669 #: src/src/i2p/susi/webmail/WebMail.java:1708
#, java-format #, java-format
msgid "1 Byte" msgid "1 Byte"
msgid_plural "{0} Bytes" msgid_plural "{0} Bytes"
msgstr[0] "1 Byte" msgstr[0] "1 Byte"
msgstr[1] "{0} Bytes" msgstr[1] "{0} Bytes"
#: src/src/i2p/susi/webmail/WebMail.java:1674 #: src/src/i2p/susi/webmail/WebMail.java:1713
msgid "Mark All" msgid "Mark All"
msgstr "Alles markieren" msgstr "Alles markieren"
#: src/src/i2p/susi/webmail/WebMail.java:1675 #: src/src/i2p/susi/webmail/WebMail.java:1714
msgid "Invert Selection" msgid "Invert Selection"
msgstr "Markierung umkehren" msgstr "Markierung umkehren"
#: src/src/i2p/susi/webmail/WebMail.java:1676 #: src/src/i2p/susi/webmail/WebMail.java:1715
msgid "Clear" msgid "Clear"
msgstr "Verwerfen" msgstr "Verwerfen"
#: src/src/i2p/susi/webmail/WebMail.java:1679 #: src/src/i2p/susi/webmail/WebMail.java:1718
#: src/src/i2p/susi/webmail/WebMail.java:1680 #: src/src/i2p/susi/webmail/WebMail.java:1719
msgid "First" msgid "First"
msgstr "erste" msgstr "erste"
#: src/src/i2p/susi/webmail/WebMail.java:1679 #: src/src/i2p/susi/webmail/WebMail.java:1718
#: src/src/i2p/susi/webmail/WebMail.java:1680 #: src/src/i2p/susi/webmail/WebMail.java:1719
#: src/src/i2p/susi/webmail/WebMail.java:1715 #: src/src/i2p/susi/webmail/WebMail.java:1754
msgid "Previous" msgid "Previous"
msgstr "vorherige" msgstr "vorherige"
#: src/src/i2p/susi/webmail/WebMail.java:1681 #: src/src/i2p/susi/webmail/WebMail.java:1720
#, java-format #, java-format
msgid "Page {0} of {1}" msgid "Page {0} of {1}"
msgstr "Seite {0} von {1}" msgstr "Seite {0} von {1}"
#: src/src/i2p/susi/webmail/WebMail.java:1683 #: src/src/i2p/susi/webmail/WebMail.java:1722
#: src/src/i2p/susi/webmail/WebMail.java:1684 #: src/src/i2p/susi/webmail/WebMail.java:1723
msgid "Last" msgid "Last"
msgstr "letzte" msgstr "letzte"
#: src/src/i2p/susi/webmail/WebMail.java:1683 #: src/src/i2p/susi/webmail/WebMail.java:1722
#: src/src/i2p/susi/webmail/WebMail.java:1684 #: src/src/i2p/susi/webmail/WebMail.java:1723
#: src/src/i2p/susi/webmail/WebMail.java:1716 #: src/src/i2p/susi/webmail/WebMail.java:1755
msgid "Next" msgid "Next"
msgstr "nächste" msgstr "nächste"
#: src/src/i2p/susi/webmail/WebMail.java:1687 #: src/src/i2p/susi/webmail/WebMail.java:1726
msgid "Pagesize:" msgid "Pagesize:"
msgstr "Seitengröße" msgstr "Seitengröße"
#: src/src/i2p/susi/webmail/WebMail.java:1688 #: src/src/i2p/susi/webmail/WebMail.java:1727
msgid "Set" msgid "Set"
msgstr "festlegen" msgstr "festlegen"
#: src/src/i2p/susi/webmail/WebMail.java:1698 #: src/src/i2p/susi/webmail/WebMail.java:1737
msgid "Really delete this message?" msgid "Really delete this message?"
msgstr "Diese Nachricht wirklich löschen?" msgstr "Diese Nachricht wirklich löschen?"
#: src/src/i2p/susi/webmail/WebMail.java:1698 #: src/src/i2p/susi/webmail/WebMail.java:1737
msgid "Yes, really delete it!" msgid "Yes, really delete it!"
msgstr "Ja, wirklich löschen" msgstr "Ja, wirklich löschen"
#: src/src/i2p/susi/webmail/WebMail.java:1717 #: src/src/i2p/susi/webmail/WebMail.java:1756
msgid "Back to Folder" msgid "Back to Folder"
msgstr "Zurück zur Übersicht" msgstr "Zurück zur Übersicht"
#: src/src/i2p/susi/webmail/WebMail.java:1724 #: src/src/i2p/susi/webmail/WebMail.java:1763
msgid "Date:" msgid "Date:"
msgstr "Datum:" msgstr "Datum:"
#: src/src/i2p/susi/webmail/WebMail.java:1735 #: src/src/i2p/susi/webmail/WebMail.java:1774
msgid "Could not fetch mail." msgid "Could not fetch mail."
msgstr "Konnte Nachrichten nicht abrufen." msgstr "Konnte Nachrichten nicht abrufen."

View File

@ -9,7 +9,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-02-06 02:33+0000\n" "POT-Creation-Date: 2013-09-20 10:12+0000\n"
"PO-Revision-Date: 2011-12-13 14:16+0000\n" "PO-Revision-Date: 2011-12-13 14:16+0000\n"
"Last-Translator: Martin Svensson <digitalmannen@gmail.com>\n" "Last-Translator: Martin Svensson <digitalmannen@gmail.com>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.net/projects/p/I2P/" "Language-Team: Swedish (Sweden) (http://www.transifex.net/projects/p/I2P/"
@ -20,429 +20,429 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: src/src/i2p/susi/webmail/WebMail.java:445 #: src/src/i2p/susi/webmail/WebMail.java:447
msgid "unknown" msgid "unknown"
msgstr "okänd" msgstr "okänd"
#: src/src/i2p/susi/webmail/WebMail.java:464 #: src/src/i2p/susi/webmail/WebMail.java:466
msgid "Warning: no transfer encoding found, fallback to 7bit." msgid "Warning: no transfer encoding found, fallback to 7bit."
msgstr "" msgstr ""
"Varning: ingen överförings kodning hittats, återgår till att använda 7bit." "Varning: ingen överförings kodning hittats, återgår till att använda 7bit."
#: src/src/i2p/susi/webmail/WebMail.java:469 #: src/src/i2p/susi/webmail/WebMail.java:471
#, java-format #, java-format
msgid "No encoder found for encoding \\''{0}\\''." msgid "No encoder found for encoding \\''{0}\\''."
msgstr "Ingen encoder hittades för kodning \\''{0}\\''." msgstr "Ingen encoder hittades för kodning \\''{0}\\''."
#: src/src/i2p/susi/webmail/WebMail.java:475 #: src/src/i2p/susi/webmail/WebMail.java:477
msgid "Warning: no charset found, fallback to US-ASCII." msgid "Warning: no charset found, fallback to US-ASCII."
msgstr "Varning: ingen teckenuppsättning hittats, återgår till US-ASCII." msgstr "Varning: ingen teckenuppsättning hittats, återgår till US-ASCII."
#: src/src/i2p/susi/webmail/WebMail.java:489 #: src/src/i2p/susi/webmail/WebMail.java:491
#, java-format #, java-format
msgid "Charset \\''{0}\\'' not supported." msgid "Charset \\''{0}\\'' not supported."
msgstr "Teckenuppsättning \\''{0}\\' stöds inte." msgstr "Teckenuppsättning \\''{0}\\' stöds inte."
#: src/src/i2p/susi/webmail/WebMail.java:493 #: src/src/i2p/susi/webmail/WebMail.java:495
#, java-format #, java-format
msgid "Part ({0}) not shown, because of {1}" msgid "Part ({0}) not shown, because of {1}"
msgstr "Del ({0}) visas inte på grund av {1}" msgstr "Del ({0}) visas inte på grund av {1}"
#: src/src/i2p/susi/webmail/WebMail.java:516 #: src/src/i2p/susi/webmail/WebMail.java:518
msgid "Download" msgid "Download"
msgstr "Hämta" msgstr "Hämta"
#: src/src/i2p/susi/webmail/WebMail.java:516 #: src/src/i2p/susi/webmail/WebMail.java:518
msgid "File is packed into a zipfile for security reasons." msgid "File is packed into a zipfile for security reasons."
msgstr "Filen packas till zipfil av säkerhetsskäl." msgstr "Filen packas till zipfil av säkerhetsskäl."
#: src/src/i2p/susi/webmail/WebMail.java:516 #: src/src/i2p/susi/webmail/WebMail.java:518
#, java-format #, java-format
msgid "attachment ({0})." msgid "attachment ({0})."
msgstr "bilaga ({0})." msgstr "bilaga ({0})."
#: src/src/i2p/susi/webmail/WebMail.java:520 #: src/src/i2p/susi/webmail/WebMail.java:522
#, java-format #, java-format
msgid "Attachment ({0})." msgid "Attachment ({0})."
msgstr "Bilaga ({0})." msgstr "Bilaga ({0})."
#: src/src/i2p/susi/webmail/WebMail.java:570 #: src/src/i2p/susi/webmail/WebMail.java:572
msgid "Need username for authentication." msgid "Need username for authentication."
msgstr "Behöver användarnamn för autentisering." msgstr "Behöver användarnamn för autentisering."
#: src/src/i2p/susi/webmail/WebMail.java:574 #: src/src/i2p/susi/webmail/WebMail.java:576
msgid "Need password for authentication." msgid "Need password for authentication."
msgstr "Behöver lösenord för autentisering." msgstr "Behöver lösenord för autentisering."
#: src/src/i2p/susi/webmail/WebMail.java:578 #: src/src/i2p/susi/webmail/WebMail.java:580
msgid "Need hostname for connect." msgid "Need hostname for connect."
msgstr "Behöver värd namn för att ansluta." msgstr "Behöver värd namn för att ansluta."
#: src/src/i2p/susi/webmail/WebMail.java:583 #: src/src/i2p/susi/webmail/WebMail.java:585
msgid "Need port number for pop3 connect." msgid "Need port number for pop3 connect."
msgstr "Behöver portnummer för POP3 anslutning." msgstr "Behöver portnummer för POP3 anslutning."
#: src/src/i2p/susi/webmail/WebMail.java:590 #: src/src/i2p/susi/webmail/WebMail.java:592
msgid "POP3 port number is not in range 0..65535." msgid "POP3 port number is not in range 0..65535."
msgstr "POP3 portnummer är inte inom intervallet 0 .. 65535." msgstr "POP3 portnummer är inte inom intervallet 0 .. 65535."
#: src/src/i2p/susi/webmail/WebMail.java:596 #: src/src/i2p/susi/webmail/WebMail.java:598
msgid "POP3 port number is invalid." msgid "POP3 port number is invalid."
msgstr "POP3 portnummer är ogiltigt" msgstr "POP3 portnummer är ogiltigt"
#: src/src/i2p/susi/webmail/WebMail.java:602 #: src/src/i2p/susi/webmail/WebMail.java:604
msgid "Need port number for smtp connect." msgid "Need port number for smtp connect."
msgstr "Behöver portnummer för SMTP anslutning." msgstr "Behöver portnummer för SMTP anslutning."
#: src/src/i2p/susi/webmail/WebMail.java:609 #: src/src/i2p/susi/webmail/WebMail.java:611
msgid "SMTP port number is not in range 0..65535." msgid "SMTP port number is not in range 0..65535."
msgstr "SMTP portnumret är inte inom intervallet 0 .. 65535." msgstr "SMTP portnumret är inte inom intervallet 0 .. 65535."
#: src/src/i2p/susi/webmail/WebMail.java:615 #: src/src/i2p/susi/webmail/WebMail.java:617
msgid "SMTP port number is invalid." msgid "SMTP port number is invalid."
msgstr "SMTP portnummer ör ogiltigt" msgstr "SMTP portnummer ör ogiltigt"
#: src/src/i2p/susi/webmail/WebMail.java:662 #: src/src/i2p/susi/webmail/WebMail.java:664
msgid "User logged out." msgid "User logged out."
msgstr "Användare loggade ut." msgstr "Användare loggade ut."
#: src/src/i2p/susi/webmail/WebMail.java:666 #: src/src/i2p/susi/webmail/WebMail.java:668
msgid "Internal error, lost connection." msgid "Internal error, lost connection."
msgstr "Internt fel, tappade anslutningen." msgstr "Internt fel, tappade anslutningen."
#: src/src/i2p/susi/webmail/WebMail.java:762 #: src/src/i2p/susi/webmail/WebMail.java:764
#, java-format #, java-format
msgid "On {0} {1} wrote:" msgid "On {0} {1} wrote:"
msgstr "Den {0} {1} skrev:" msgstr "Den {0} {1} skrev:"
#: src/src/i2p/susi/webmail/WebMail.java:809 #: src/src/i2p/susi/webmail/WebMail.java:811
msgid "begin forwarded mail" msgid "begin forwarded mail"
msgstr "börjar vidarebefordra e-post" msgstr "börjar vidarebefordra e-post"
#: src/src/i2p/susi/webmail/WebMail.java:831 #: src/src/i2p/susi/webmail/WebMail.java:833
msgid "end forwarded mail" msgid "end forwarded mail"
msgstr "slutar vidarebefordra e-post" msgstr "slutar vidarebefordra e-post"
#: src/src/i2p/susi/webmail/WebMail.java:838 #: src/src/i2p/susi/webmail/WebMail.java:840
#: src/src/i2p/susi/webmail/WebMail.java:1731 #: src/src/i2p/susi/webmail/WebMail.java:1770
msgid "Could not fetch mail body." msgid "Could not fetch mail body."
msgstr "Kunde inte hämta e-postets brödtext." msgstr "Kunde inte hämta e-postets brödtext."
#: src/src/i2p/susi/webmail/WebMail.java:866 #: src/src/i2p/susi/webmail/WebMail.java:868
msgid "Message id not valid." msgid "Message id not valid."
msgstr "Meddelande id är inte giltigt" msgstr "Meddelande id är inte giltigt"
#: src/src/i2p/susi/webmail/WebMail.java:949 #: src/src/i2p/susi/webmail/WebMail.java:951
#, java-format #, java-format
msgid "No Encoding found for {0}" msgid "No Encoding found for {0}"
msgstr "Ingen teckenkodning hittades för {0}" msgstr "Ingen teckenkodning hittades för {0}"
#: src/src/i2p/susi/webmail/WebMail.java:953 #: src/src/i2p/susi/webmail/WebMail.java:955
#, java-format #, java-format
msgid "Could not encode data: {0}" msgid "Could not encode data: {0}"
msgstr "Kunde inte koda data: {0}" msgstr "Kunde inte koda data: {0}"
#: src/src/i2p/susi/webmail/WebMail.java:958 #: src/src/i2p/susi/webmail/WebMail.java:960
#, java-format #, java-format
msgid "Error reading uploaded file: {0}" msgid "Error reading uploaded file: {0}"
msgstr "Fel vid läsning av uppladdad fil: {0}" msgstr "Fel vid läsning av uppladdad fil: {0}"
#: src/src/i2p/susi/webmail/WebMail.java:1036 #: src/src/i2p/susi/webmail/WebMail.java:1038
msgid "Error parsing download parameter." msgid "Error parsing download parameter."
msgstr "Fel vid tolkning av nedladdnings parameter." msgstr "Fel vid tolkning av nedladdnings parameter."
#: src/src/i2p/susi/webmail/WebMail.java:1080 #: src/src/i2p/susi/webmail/WebMail.java:1082
msgid "Invalid pagesize number, resetting to default value." msgid "Invalid pagesize number, resetting to default value."
msgstr "Ogiltigt sidstorleks antal, återställer till standard värde." msgstr "Ogiltigt sidstorleks antal, återställer till standard värde."
#: src/src/i2p/susi/webmail/WebMail.java:1104 #: src/src/i2p/susi/webmail/WebMail.java:1106
msgid "No messages marked for deletion." msgid "No messages marked for deletion."
msgstr "Inga meddelanden var märkta för radering" msgstr "Inga meddelanden var märkta för radering"
#: src/src/i2p/susi/webmail/WebMail.java:1124 #: src/src/i2p/susi/webmail/WebMail.java:1126
#, java-format #, java-format
msgid "Error deleting message: {0}" msgid "Error deleting message: {0}"
msgstr "Fel vid raderande av meddelande: {0}" msgstr "Fel vid raderande av meddelande: {0}"
#: src/src/i2p/susi/webmail/WebMail.java:1135 #: src/src/i2p/susi/webmail/WebMail.java:1137
#, java-format #, java-format
msgid "1 message deleted." msgid "1 message deleted."
msgid_plural "{0} messages deleted." msgid_plural "{0} messages deleted."
msgstr[0] "1 meddelande raderart." msgstr[0] "1 meddelande raderart."
msgstr[1] "{0} meddelanden raderade" msgstr[1] "{0} meddelanden raderade"
#: src/src/i2p/susi/webmail/WebMail.java:1278 #: src/src/i2p/susi/webmail/WebMail.java:1313
#: src/src/i2p/susi/webmail/WebMail.java:1615 #: src/src/i2p/susi/webmail/WebMail.java:1654
msgid "Login" msgid "Login"
msgstr "Logga in" msgstr "Logga in"
#: src/src/i2p/susi/webmail/WebMail.java:1280 #: src/src/i2p/susi/webmail/WebMail.java:1315
#, java-format #, java-format
msgid "1 Message" msgid "1 Message"
msgid_plural "{0} Messages" msgid_plural "{0} Messages"
msgstr[0] "1 meddelande" msgstr[0] "1 meddelande"
msgstr[1] "{0} meddelanden" msgstr[1] "{0} meddelanden"
#: src/src/i2p/susi/webmail/WebMail.java:1282 #: src/src/i2p/susi/webmail/WebMail.java:1317
msgid "Show Message" msgid "Show Message"
msgstr "Visa meddelande" msgstr "Visa meddelande"
#: src/src/i2p/susi/webmail/WebMail.java:1344 #: src/src/i2p/susi/webmail/WebMail.java:1383
#, java-format #, java-format
msgid "Error decoding content: {0}" msgid "Error decoding content: {0}"
msgstr "Fel vid avkodning av innehåll: {0}" msgstr "Fel vid avkodning av innehåll: {0}"
#: src/src/i2p/susi/webmail/WebMail.java:1349 #: src/src/i2p/susi/webmail/WebMail.java:1388
msgid "Error decoding content: No encoder found." msgid "Error decoding content: No encoder found."
msgstr "Fel vid avkodning av innehåll: Ingen encoder hittades." msgstr "Fel vid avkodning av innehåll: Ingen encoder hittades."
#: src/src/i2p/susi/webmail/WebMail.java:1396 #: src/src/i2p/susi/webmail/WebMail.java:1435
msgid "no subject" msgid "no subject"
msgstr "inget ämne" msgstr "inget ämne"
#: src/src/i2p/susi/webmail/WebMail.java:1413 #: src/src/i2p/susi/webmail/WebMail.java:1452
msgid "Found no valid sender address." msgid "Found no valid sender address."
msgstr "Hittade ingen giltig avsändaradress." msgstr "Hittade ingen giltig avsändaradress."
#: src/src/i2p/susi/webmail/WebMail.java:1419 #: src/src/i2p/susi/webmail/WebMail.java:1458
#, java-format #, java-format
msgid "Found no valid address in \\''{0}\\''." msgid "Found no valid address in \\''{0}\\''."
msgstr "Hittade ingen giltig adress i \\''{0}\\''." msgstr "Hittade ingen giltig adress i \\''{0}\\''."
#: src/src/i2p/susi/webmail/WebMail.java:1438 #: src/src/i2p/susi/webmail/WebMail.java:1477
msgid "No recipients found." msgid "No recipients found."
msgstr "Inga mottagare funna" msgstr "Inga mottagare funna"
#: src/src/i2p/susi/webmail/WebMail.java:1445 #: src/src/i2p/susi/webmail/WebMail.java:1484
msgid "Quoted printable encoder not available." msgid "Quoted printable encoder not available."
msgstr "Citerad utskrivbar encoder inte tillgänglig." msgstr "Citerad utskrivbar encoder inte tillgänglig."
#: src/src/i2p/susi/webmail/WebMail.java:1450 #: src/src/i2p/susi/webmail/WebMail.java:1489
msgid "Header line encoder not available." msgid "Header line encoder not available."
msgstr "Header radens encoder är inte tillgänglig." msgstr "Header radens encoder är inte tillgänglig."
#: src/src/i2p/susi/webmail/WebMail.java:1501 #: src/src/i2p/susi/webmail/WebMail.java:1540
msgid "Mail sent." msgid "Mail sent."
msgstr "E-post skickat" msgstr "E-post skickat"
#: src/src/i2p/susi/webmail/WebMail.java:1540 #: src/src/i2p/susi/webmail/WebMail.java:1579
msgid "Send" msgid "Send"
msgstr "Skicka" msgstr "Skicka"
#: src/src/i2p/susi/webmail/WebMail.java:1541 #: src/src/i2p/susi/webmail/WebMail.java:1580
msgid "Cancel" msgid "Cancel"
msgstr "Avbryt" msgstr "Avbryt"
#: src/src/i2p/susi/webmail/WebMail.java:1542 #: src/src/i2p/susi/webmail/WebMail.java:1581
msgid "Delete Attachment" msgid "Delete Attachment"
msgstr "Radera bilaga" msgstr "Radera bilaga"
#: src/src/i2p/susi/webmail/WebMail.java:1543 #: src/src/i2p/susi/webmail/WebMail.java:1582
#: src/src/i2p/susi/webmail/WebMail.java:1637 #: src/src/i2p/susi/webmail/WebMail.java:1676
#: src/src/i2p/susi/webmail/WebMail.java:1718 #: src/src/i2p/susi/webmail/WebMail.java:1757
msgid "Reload Config" msgid "Reload Config"
msgstr "Ladda om konfiguration" msgstr "Ladda om konfiguration"
#: src/src/i2p/susi/webmail/WebMail.java:1544 #: src/src/i2p/susi/webmail/WebMail.java:1583
#: src/src/i2p/susi/webmail/WebMail.java:1638 #: src/src/i2p/susi/webmail/WebMail.java:1677
#: src/src/i2p/susi/webmail/WebMail.java:1719 #: src/src/i2p/susi/webmail/WebMail.java:1758
msgid "Logout" msgid "Logout"
msgstr "Logga ut" msgstr "Logga ut"
#: src/src/i2p/susi/webmail/WebMail.java:1567 #: src/src/i2p/susi/webmail/WebMail.java:1606
#: src/src/i2p/susi/webmail/WebMail.java:1723 #: src/src/i2p/susi/webmail/WebMail.java:1762
msgid "From:" msgid "From:"
msgstr "Från:" msgstr "Från:"
#: src/src/i2p/susi/webmail/WebMail.java:1568 #: src/src/i2p/susi/webmail/WebMail.java:1607
msgid "To:" msgid "To:"
msgstr "Till:" msgstr "Till:"
#: src/src/i2p/susi/webmail/WebMail.java:1569 #: src/src/i2p/susi/webmail/WebMail.java:1608
msgid "Cc:" msgid "Cc:"
msgstr "Cc:" msgstr "Cc:"
#: src/src/i2p/susi/webmail/WebMail.java:1570 #: src/src/i2p/susi/webmail/WebMail.java:1609
msgid "Bcc:" msgid "Bcc:"
msgstr "Bcc:" msgstr "Bcc:"
#: src/src/i2p/susi/webmail/WebMail.java:1571 #: src/src/i2p/susi/webmail/WebMail.java:1610
#: src/src/i2p/susi/webmail/WebMail.java:1725 #: src/src/i2p/susi/webmail/WebMail.java:1764
msgid "Subject:" msgid "Subject:"
msgstr "Ärende:" msgstr "Ärende:"
#: src/src/i2p/susi/webmail/WebMail.java:1572 #: src/src/i2p/susi/webmail/WebMail.java:1611
msgid "Bcc to self" msgid "Bcc to self"
msgstr "Bcc till själv" msgstr "Bcc till själv"
#: src/src/i2p/susi/webmail/WebMail.java:1575 #: src/src/i2p/susi/webmail/WebMail.java:1614
msgid "New Attachment:" msgid "New Attachment:"
msgstr "Ny bilaga:" msgstr "Ny bilaga:"
#: src/src/i2p/susi/webmail/WebMail.java:1575 #: src/src/i2p/susi/webmail/WebMail.java:1614
msgid "Upload File" msgid "Upload File"
msgstr "Ladda upp fil" msgstr "Ladda upp fil"
#: src/src/i2p/susi/webmail/WebMail.java:1581 #: src/src/i2p/susi/webmail/WebMail.java:1620
msgid "Attachments:" msgid "Attachments:"
msgstr "Bilagor:" msgstr "Bilagor:"
#. current postman hq length limits 16/12, new postman version 32/32 #. current postman hq length limits 16/12, new postman version 32/32
#: src/src/i2p/susi/webmail/WebMail.java:1604 #: src/src/i2p/susi/webmail/WebMail.java:1643
msgid "User" msgid "User"
msgstr "Användare" msgstr "Användare"
#: src/src/i2p/susi/webmail/WebMail.java:1605 #: src/src/i2p/susi/webmail/WebMail.java:1644
msgid "Password" msgid "Password"
msgstr "Lösenord" msgstr "Lösenord"
#: src/src/i2p/susi/webmail/WebMail.java:1610 #: src/src/i2p/susi/webmail/WebMail.java:1649
msgid "Host" msgid "Host"
msgstr "Värd" msgstr "Värd"
#: src/src/i2p/susi/webmail/WebMail.java:1611 #: src/src/i2p/susi/webmail/WebMail.java:1650
msgid "POP3-Port" msgid "POP3-Port"
msgstr "POP3-port" msgstr "POP3-port"
#: src/src/i2p/susi/webmail/WebMail.java:1612 #: src/src/i2p/susi/webmail/WebMail.java:1651
msgid "SMTP-Port" msgid "SMTP-Port"
msgstr "SMTP-port" msgstr "SMTP-port"
#: src/src/i2p/susi/webmail/WebMail.java:1615 #: src/src/i2p/susi/webmail/WebMail.java:1654
msgid "Reset" msgid "Reset"
msgstr "Återställ" msgstr "Återställ"
#: src/src/i2p/susi/webmail/WebMail.java:1616 #: src/src/i2p/susi/webmail/WebMail.java:1655
msgid "Learn about I2P mail" msgid "Learn about I2P mail"
msgstr "Lär mer om I2P e-post" msgstr "Lär mer om I2P e-post"
#: src/src/i2p/susi/webmail/WebMail.java:1617 #: src/src/i2p/susi/webmail/WebMail.java:1656
msgid "Create Account" msgid "Create Account"
msgstr "Skapa konto" msgstr "Skapa konto"
#: src/src/i2p/susi/webmail/WebMail.java:1629 #: src/src/i2p/susi/webmail/WebMail.java:1668
msgid "Really delete the marked messages?" msgid "Really delete the marked messages?"
msgstr "Vill du verkligen radera valda meddelanden?" msgstr "Vill du verkligen radera valda meddelanden?"
#: src/src/i2p/susi/webmail/WebMail.java:1629 #: src/src/i2p/susi/webmail/WebMail.java:1668
msgid "Yes, really delete them!" msgid "Yes, really delete them!"
msgstr "Ja, radera dem!" msgstr "Ja, radera dem!"
#: src/src/i2p/susi/webmail/WebMail.java:1631 #: src/src/i2p/susi/webmail/WebMail.java:1670
#: src/src/i2p/susi/webmail/WebMail.java:1710 #: src/src/i2p/susi/webmail/WebMail.java:1749
msgid "New" msgid "New"
msgstr "Ny" msgstr "Ny"
#: src/src/i2p/susi/webmail/WebMail.java:1632 #: src/src/i2p/susi/webmail/WebMail.java:1671
#: src/src/i2p/susi/webmail/WebMail.java:1711 #: src/src/i2p/susi/webmail/WebMail.java:1750
msgid "Reply" msgid "Reply"
msgstr "Svara" msgstr "Svara"
#: src/src/i2p/susi/webmail/WebMail.java:1633 #: src/src/i2p/susi/webmail/WebMail.java:1672
#: src/src/i2p/susi/webmail/WebMail.java:1712 #: src/src/i2p/susi/webmail/WebMail.java:1751
msgid "Reply All" msgid "Reply All"
msgstr "Svara alla" msgstr "Svara alla"
#: src/src/i2p/susi/webmail/WebMail.java:1634 #: src/src/i2p/susi/webmail/WebMail.java:1673
#: src/src/i2p/susi/webmail/WebMail.java:1713 #: src/src/i2p/susi/webmail/WebMail.java:1752
msgid "Forward" msgid "Forward"
msgstr "Vidarebefodera" msgstr "Vidarebefodera"
#: src/src/i2p/susi/webmail/WebMail.java:1635 #: src/src/i2p/susi/webmail/WebMail.java:1674
#: src/src/i2p/susi/webmail/WebMail.java:1714 #: src/src/i2p/susi/webmail/WebMail.java:1753
msgid "Delete" msgid "Delete"
msgstr "Radera" msgstr "Radera"
#: src/src/i2p/susi/webmail/WebMail.java:1636 #: src/src/i2p/susi/webmail/WebMail.java:1675
msgid "Check Mail" msgid "Check Mail"
msgstr "Kolla e-post" msgstr "Kolla e-post"
#: src/src/i2p/susi/webmail/WebMail.java:1640 #: src/src/i2p/susi/webmail/WebMail.java:1679
msgid "Sender" msgid "Sender"
msgstr "Avsändare" msgstr "Avsändare"
#: src/src/i2p/susi/webmail/WebMail.java:1641 #: src/src/i2p/susi/webmail/WebMail.java:1680
msgid "Subject" msgid "Subject"
msgstr "Ärende" msgstr "Ärende"
#: src/src/i2p/susi/webmail/WebMail.java:1642 #: src/src/i2p/susi/webmail/WebMail.java:1681
msgid "Date" msgid "Date"
msgstr "Datum" msgstr "Datum"
#: src/src/i2p/susi/webmail/WebMail.java:1643 #: src/src/i2p/susi/webmail/WebMail.java:1682
msgid "Size" msgid "Size"
msgstr "Storlek" msgstr "Storlek"
#: src/src/i2p/susi/webmail/WebMail.java:1669 #: src/src/i2p/susi/webmail/WebMail.java:1708
#, java-format #, java-format
msgid "1 Byte" msgid "1 Byte"
msgid_plural "{0} Bytes" msgid_plural "{0} Bytes"
msgstr[0] "1 Byte" msgstr[0] "1 Byte"
msgstr[1] "{0} Bytes" msgstr[1] "{0} Bytes"
#: src/src/i2p/susi/webmail/WebMail.java:1674 #: src/src/i2p/susi/webmail/WebMail.java:1713
msgid "Mark All" msgid "Mark All"
msgstr "Markera alla" msgstr "Markera alla"
#: src/src/i2p/susi/webmail/WebMail.java:1675 #: src/src/i2p/susi/webmail/WebMail.java:1714
msgid "Invert Selection" msgid "Invert Selection"
msgstr "Invertera urvalet" msgstr "Invertera urvalet"
#: src/src/i2p/susi/webmail/WebMail.java:1676 #: src/src/i2p/susi/webmail/WebMail.java:1715
msgid "Clear" msgid "Clear"
msgstr "Rensa " msgstr "Rensa "
#: src/src/i2p/susi/webmail/WebMail.java:1679 #: src/src/i2p/susi/webmail/WebMail.java:1718
#: src/src/i2p/susi/webmail/WebMail.java:1680 #: src/src/i2p/susi/webmail/WebMail.java:1719
msgid "First" msgid "First"
msgstr "Första" msgstr "Första"
#: src/src/i2p/susi/webmail/WebMail.java:1679 #: src/src/i2p/susi/webmail/WebMail.java:1718
#: src/src/i2p/susi/webmail/WebMail.java:1680 #: src/src/i2p/susi/webmail/WebMail.java:1719
#: src/src/i2p/susi/webmail/WebMail.java:1715 #: src/src/i2p/susi/webmail/WebMail.java:1754
msgid "Previous" msgid "Previous"
msgstr "Föregående" msgstr "Föregående"
#: src/src/i2p/susi/webmail/WebMail.java:1681 #: src/src/i2p/susi/webmail/WebMail.java:1720
#, java-format #, java-format
msgid "Page {0} of {1}" msgid "Page {0} of {1}"
msgstr "Sida {0} av {1}" msgstr "Sida {0} av {1}"
#: src/src/i2p/susi/webmail/WebMail.java:1683 #: src/src/i2p/susi/webmail/WebMail.java:1722
#: src/src/i2p/susi/webmail/WebMail.java:1684 #: src/src/i2p/susi/webmail/WebMail.java:1723
msgid "Last" msgid "Last"
msgstr "Sista" msgstr "Sista"
#: src/src/i2p/susi/webmail/WebMail.java:1683 #: src/src/i2p/susi/webmail/WebMail.java:1722
#: src/src/i2p/susi/webmail/WebMail.java:1684 #: src/src/i2p/susi/webmail/WebMail.java:1723
#: src/src/i2p/susi/webmail/WebMail.java:1716 #: src/src/i2p/susi/webmail/WebMail.java:1755
msgid "Next" msgid "Next"
msgstr "Nästa" msgstr "Nästa"
#: src/src/i2p/susi/webmail/WebMail.java:1687 #: src/src/i2p/susi/webmail/WebMail.java:1726
msgid "Pagesize:" msgid "Pagesize:"
msgstr "Pagesize:" msgstr "Pagesize:"
#: src/src/i2p/susi/webmail/WebMail.java:1688 #: src/src/i2p/susi/webmail/WebMail.java:1727
msgid "Set" msgid "Set"
msgstr "Ställ" msgstr "Ställ"
#: src/src/i2p/susi/webmail/WebMail.java:1698 #: src/src/i2p/susi/webmail/WebMail.java:1737
msgid "Really delete this message?" msgid "Really delete this message?"
msgstr "Vill du verkligen radera detta meddelande?" msgstr "Vill du verkligen radera detta meddelande?"
#: src/src/i2p/susi/webmail/WebMail.java:1698 #: src/src/i2p/susi/webmail/WebMail.java:1737
msgid "Yes, really delete it!" msgid "Yes, really delete it!"
msgstr "Ja, radera det verkligen!" msgstr "Ja, radera det verkligen!"
#: src/src/i2p/susi/webmail/WebMail.java:1717 #: src/src/i2p/susi/webmail/WebMail.java:1756
msgid "Back to Folder" msgid "Back to Folder"
msgstr "Tillbaka till mapp" msgstr "Tillbaka till mapp"
#: src/src/i2p/susi/webmail/WebMail.java:1724 #: src/src/i2p/susi/webmail/WebMail.java:1763
msgid "Date:" msgid "Date:"
msgstr "Datum:" msgstr "Datum:"
#: src/src/i2p/susi/webmail/WebMail.java:1735 #: src/src/i2p/susi/webmail/WebMail.java:1774
msgid "Could not fetch mail." msgid "Could not fetch mail."
msgstr "Kunde inte hämta e-post." msgstr "Kunde inte hämta e-post."

View File

@ -1380,6 +1380,7 @@
<exec executable="tests/scripts/checkpo.sh" failonerror="true" /> <exec executable="tests/scripts/checkpo.sh" failonerror="true" />
<exec executable="tests/scripts/checkutf8.sh" failonerror="true" /> <exec executable="tests/scripts/checkutf8.sh" failonerror="true" />
<exec executable="tests/scripts/checkxml.sh" failonerror="true" /> <exec executable="tests/scripts/checkxml.sh" failonerror="true" />
<exec executable="tests/scripts/checkscripts.sh" failonerror="true" />
</target> </target>
@ -1496,6 +1497,7 @@
</condition> </condition>
</fail> </fail>
<echo message="Key file is ${release.privkey}" /> <echo message="Key file is ${release.privkey}" />
<!-- now build and verify the unpacked sud from the unpacked zip -->
<java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true"> <java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true">
<classpath> <classpath>
<pathelement location="build/i2p.jar" /> <pathelement location="build/i2p.jar" />
@ -1528,7 +1530,7 @@
<arg value="showversion" /> <arg value="showversion" />
<arg value="i2pupdate.sud" /> <arg value="i2pupdate.sud" />
</java> </java>
<!-- now build and verify the packed sud from the packed zip --> <!-- now build and verify the packed su2 from the packed zip -->
<java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true"> <java classname="net.i2p.crypto.TrustedUpdate" fork="true" failonerror="true">
<classpath> <classpath>
<pathelement location="build/i2p.jar" /> <pathelement location="build/i2p.jar" />
@ -1561,6 +1563,59 @@
<arg value="showversion" /> <arg value="showversion" />
<arg value="i2pupdate.su2" /> <arg value="i2pupdate.su2" />
</java> </java>
<!-- now build and verify the packed su3 from the packed zip -->
<input message="Enter su3 private signing key store:" addproperty="release.privkey.su3" />
<fail message="You must enter a path." >
<condition>
<equals arg1="${release.privkey.su3}" arg2=""/>
</condition>
</fail>
<input message="Enter key name (you@mail.i2p):" addproperty="release.signer.su3" />
<fail message="You must enter a name." >
<condition>
<equals arg1="${release.signer.su3}" arg2=""/>
</condition>
</fail>
<input message="Enter key password for ${release.signer.su3}:" addproperty="release.password.su3" />
<fail message="You must enter a password." >
<condition>
<equals arg1="${release.password.su3}" arg2=""/>
</condition>
</fail>
<java classname="net.i2p.crypto.SU3File" inputstring="${release.password.su3}" fork="true" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
</classpath>
<arg value="sign" />
<arg value="-c" />
<arg value="ROUTER" />
<arg value="-t" />
<arg value="RSA_SHA512_4096" />
<arg value="i2pupdate200.zip" />
<arg value="i2pupdate.su3" />
<arg value="${release.privkey.su3}" />
<arg value="${release.number}" />
<arg value="${release.signer.su3}" />
</java>
<echo message="Verify version and VALID signature:" />
<java classname="net.i2p.crypto.SU3File" fork="true" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
</classpath>
<!-- set base dir so it can find the pubkey cert -->
<jvmarg value="-Di2p.dir.base=installer/resources" />
<arg value="verifysig" />
<arg value="i2pupdate.su3" />
</java>
<java classname="net.i2p.crypto.SU3File" fork="true" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
</classpath>
<!-- set base dir so it can find the pubkey cert -->
<jvmarg value="-Di2p.dir.base=installer/resources" />
<arg value="showversion" />
<arg value="i2pupdate.su3" />
</java>
<!-- will this use the monotonerc file in the current workspace? --> <!-- will this use the monotonerc file in the current workspace? -->
<echo message="Checking out fresh copy into ../i2p-${release.number} for tarballing:" /> <echo message="Checking out fresh copy into ../i2p-${release.number} for tarballing:" />
<delete dir="../i2p-${release.number}" /> <delete dir="../i2p-${release.number}" />
@ -1608,6 +1663,7 @@
<arg value="i2psource_${release.number}.tar.bz2" /> <arg value="i2psource_${release.number}.tar.bz2" />
<arg value="i2pupdate_${release.number}.zip" /> <arg value="i2pupdate_${release.number}.zip" />
<arg value="i2pupdate.su2" /> <arg value="i2pupdate.su2" />
<arg value="i2pupdate.su3" />
<arg value="i2pupdate.sud" /> <arg value="i2pupdate.sud" />
<arg value="i2pinstall_${release.number}_windows.exe.sig" /> <arg value="i2pinstall_${release.number}_windows.exe.sig" />
<arg value="i2pinstall_${release.number}.jar.sig" /> <arg value="i2pinstall_${release.number}.jar.sig" />
@ -1622,6 +1678,7 @@
<arg value="i2psource_${release.number}.tar.bz2" /> <arg value="i2psource_${release.number}.tar.bz2" />
<arg value="i2pupdate_${release.number}.zip" /> <arg value="i2pupdate_${release.number}.zip" />
<arg value="i2pupdate.su2" /> <arg value="i2pupdate.su2" />
<arg value="i2pupdate.su3" />
<arg value="i2pupdate.sud" /> <arg value="i2pupdate.sud" />
<arg value="i2pinstall_${release.number}_windows.exe.sig" /> <arg value="i2pinstall_${release.number}_windows.exe.sig" />
<arg value="i2pinstall_${release.number}.jar.sig" /> <arg value="i2pinstall_${release.number}.jar.sig" />
@ -1635,6 +1692,7 @@
<arg value="i2psource_${release.number}.tar.bz2" /> <arg value="i2psource_${release.number}.tar.bz2" />
<arg value="i2pupdate_${release.number}.zip" /> <arg value="i2pupdate_${release.number}.zip" />
<arg value="i2pupdate.su2" /> <arg value="i2pupdate.su2" />
<arg value="i2pupdate.su3" />
<arg value="i2pupdate.sud" /> <arg value="i2pupdate.sud" />
</exec> </exec>
<!-- make torrent files --> <!-- make torrent files -->
@ -1656,6 +1714,15 @@
<arg value="i2pupdate-${release.number}.su2" /> <arg value="i2pupdate-${release.number}.su2" />
<arg value="http://tracker2.postman.i2p/announce.php" /> <arg value="http://tracker2.postman.i2p/announce.php" />
</java> </java>
<copy file="i2pupdate.su3" tofile="i2pupdate-${release.number}.su3" />
<java classname="org.klomp.snark.Storage" fork="true" failonerror="true">
<classpath>
<pathelement location="build/i2p.jar" />
<pathelement location="build/i2psnark.jar" />
</classpath>
<arg value="i2pupdate-${release.number}.su3" />
<arg value="http://tracker2.postman.i2p/announce.php" />
</java>
<echo message="Don't forget to mtn tag w: i2p-${release.number}" /> <echo message="Don't forget to mtn tag w: i2p-${release.number}" />
<echo message="... and mtn cert t:i2p-${release.number} branch i2p.i2p.release" /> <echo message="... and mtn cert t:i2p-${release.number} branch i2p.i2p.release" />
</target> </target>

View File

@ -1,4 +1,4 @@
#/bin/sh #!/bin/sh
(cd jcpuid ; sh build.sh ; cd ..) (cd jcpuid ; sh build.sh ; cd ..)
(cd jbigi ; sh build.sh ; cd ..) (cd jbigi ; sh build.sh ; cd ..)

View File

@ -17,6 +17,8 @@ elif [ $UNIXTYPE = "sunos" ]; then
elif [ $UNIXTYPE = "openbsd" ]; then elif [ $UNIXTYPE = "openbsd" ]; then
if [ -d /usr/local/jdk-1.7.0 ]; then if [ -d /usr/local/jdk-1.7.0 ]; then
JAVA_HOME="/usr/local/jdk-1.7.0" JAVA_HOME="/usr/local/jdk-1.7.0"
elif [ -d /usr/local/jdk-1.6.0 ]; then
JAVA_HOME="/usr/local/jdk-1.6.0"
fi fi
elif [ $UNIXTYPE = "netbsd" ]; then elif [ $UNIXTYPE = "netbsd" ]; then
if [ -d /usr/pkg/java/openjdk7 ]; then if [ -d /usr/pkg/java/openjdk7 ]; then

View File

@ -1,4 +1,4 @@
#/bin/sh #!/bin/sh
case `uname -sr` in case `uname -sr` in
MINGW*) MINGW*)

View File

@ -39,7 +39,7 @@ SunOS*|OpenBSD*|NetBSD*|*FreeBSD*|Linux*)
UNIXTYPE="linux" UNIXTYPE="linux"
fi fi
COMPILEFLAGS="-fPIC -Wall $CFLAGS" COMPILEFLAGS="-fPIC -Wall $CFLAGS"
INCLUDES="-I. -I../../jbigi/include -I$JAVA_HOME/include -I$JAVA_HOME/include/${UNIXTYPE}" INCLUDES="-I. -I../../jbigi/include -I$JAVA_HOME/include -I$JAVA_HOME/include/${UNIXTYPE} -I/usr/local/include"
LINKFLAGS="-shared -Wl,-soname,libjbigi.so" LINKFLAGS="-shared -Wl,-soname,libjbigi.so"
LIBFILE="libjbigi.so";; LIBFILE="libjbigi.so";;
*) *)
@ -49,7 +49,7 @@ esac
if [ "$1" = "dynamic" ] ; then if [ "$1" = "dynamic" ] ; then
echo "Building a jbigi lib that is dynamically linked to GMP" echo "Building a jbigi lib that is dynamically linked to GMP"
LIBPATH="-L.libs" LIBPATH="-L.libs -L/usr/local/lib"
INCLUDELIBS="-lgmp" INCLUDELIBS="-lgmp"
else else
echo "Building a jbigi lib that is statically linked to GMP" echo "Building a jbigi lib that is statically linked to GMP"
@ -59,6 +59,6 @@ fi
echo "Compiling C code..." echo "Compiling C code..."
rm -f jbigi.o $LIBFILE rm -f jbigi.o $LIBFILE
$CC -c $COMPILEFLAGS $INCLUDES ../../jbigi/src/jbigi.c || exit 1 $CC -c $COMPILEFLAGS $INCLUDES ../../jbigi/src/jbigi.c || exit 1
$CC $LINKFLAGS $INCLUDES -o $LIBFILE jbigi.o $INCLUDELIBS $STATICLIBS || exit 1 $CC $LINKFLAGS $INCLUDES -o $LIBFILE jbigi.o $INCLUDELIBS $STATICLIBS $LIBPATH || exit 1
exit 0 exit 0

View File

@ -1,21 +1,7 @@
#!/usr/bin/env bash #!/bin/sh -e
# Automatic build of so files, ignores failed builds. # Automatic build of so files, ignores failed builds.
# Place latest gmp tarball in the jbigi dir, and exec this script. # Place latest gmp tarball in the jbigi dir, and exec this script.
if [ -z "$BASH_VERSION" ]; then
echo "This script needs to be run with Bash."
echo
echo "Please install bash and then run this script with"
echo "bash $0"
exit 1
fi
#JBIGI=../../../installer/lib/jbigi/jbigi.jar
#if [ -f jbigi.jarx ] ; then
#JBIGI=../jbigi.jar
#fi
rm -f t/* jcpuid/lib/freenet/support/CPUInformation/* jbigi/lib/net/i2p/util/* rm -f t/* jcpuid/lib/freenet/support/CPUInformation/* jbigi/lib/net/i2p/util/*
( cd jcpuid ; ./build.sh ) ( cd jcpuid ; ./build.sh )
@ -32,7 +18,7 @@ mkdir t
cp jbigi/lib/net/i2p/util/* t/ cp jbigi/lib/net/i2p/util/* t/
( (
cd t cd t
for i in *.so ; { strip $i ; } for i in *.so ; do strip $i ; done
) )
cp jcpuid/lib/freenet/support/CPUInformation/* t/ cp jcpuid/lib/freenet/support/CPUInformation/* t/
@ -47,7 +33,7 @@ mkdir t
cp jbigi/lib/net/i2p/util/* t/ cp jbigi/lib/net/i2p/util/* t/
( (
cd t cd t
for i in *.so ; { strip $i ; } for i in *.so ; do strip $i ; done
) )

View File

@ -16,7 +16,7 @@ package net.i2p;
public class CoreVersion { public class CoreVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = "0.9.7.1"; public final static String VERSION = "0.9.8.1";
public static void main(String args[]) { public static void main(String args[]) {
System.out.println("I2P Core version: " + VERSION); System.out.println("I2P Core version: " + VERSION);

View File

@ -7,17 +7,13 @@ import java.io.InputStream;
import java.net.Socket; import java.net.Socket;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Locale;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.crypto.KeyStoreUtil;
import net.i2p.util.Log; import net.i2p.util.Log;
/** /**
@ -71,14 +67,14 @@ class I2CPSSLSocketFactory {
} }
File dir = new File(context.getConfigDir(), CERT_DIR); File dir = new File(context.getConfigDir(), CERT_DIR);
int adds = addCerts(dir, ks); int adds = KeyStoreUtil.addCerts(dir, ks);
int totalAdds = adds; int totalAdds = adds;
if (adds > 0) if (adds > 0)
info(context, "Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath()); info(context, "Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath());
File dir2 = new File(System.getProperty("user.dir"), CERT_DIR); File dir2 = new File(System.getProperty("user.dir"), CERT_DIR);
if (!dir.getAbsolutePath().equals(dir2.getAbsolutePath())) { if (!dir.getAbsolutePath().equals(dir2.getAbsolutePath())) {
adds = addCerts(dir2, ks); adds = KeyStoreUtil.addCerts(dir2, ks);
totalAdds += adds; totalAdds += adds;
if (adds > 0) if (adds > 0)
info(context, "Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath()); info(context, "Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath());
@ -105,82 +101,6 @@ class I2CPSSLSocketFactory {
} }
} }
/**
* Load all X509 Certs from a directory and add them to the
* trusted set of certificates in the key store
*
* @return number successfully added
*/
private static int addCerts(File dir, KeyStore ks) {
info("Looking for X509 Certificates in " + dir.getAbsolutePath());
int added = 0;
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (!f.isFile())
continue;
// use file name as alias
String alias = f.getName().toLowerCase(Locale.US);
boolean success = addCert(f, alias, ks);
if (success)
added++;
}
}
}
return added;
}
/**
* Load an X509 Cert from a file and add it to the
* trusted set of certificates in the key store
*
* @return success
*/
private static boolean addCert(File file, String alias, KeyStore ks) {
InputStream fis = null;
try {
fis = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
info("Read X509 Certificate from " + file.getAbsolutePath() +
" Issuer: " + cert.getIssuerX500Principal() +
"; Valid From: " + cert.getNotBefore() +
" To: " + cert.getNotAfter());
try {
cert.checkValidity();
} catch (CertificateExpiredException cee) {
error("Rejecting expired X509 Certificate: " + file.getAbsolutePath(), cee);
return false;
} catch (CertificateNotYetValidException cnyve) {
error("Rejecting X509 Certificate not yet valid: " + file.getAbsolutePath(), cnyve);
return false;
}
ks.setCertificateEntry(alias, cert);
info("Now trusting X509 Certificate, Issuer: " + cert.getIssuerX500Principal());
} catch (GeneralSecurityException gse) {
error("Error reading X509 Certificate: " + file.getAbsolutePath(), gse);
return false;
} catch (IOException ioe) {
error("Error reading X509 Certificate: " + file.getAbsolutePath(), ioe);
return false;
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
return true;
}
/** @since 0.9.8 */
private static void info(String msg) {
log(I2PAppContext.getGlobalContext(), Log.INFO, msg, null);
}
/** @since 0.9.8 */
private static void error(String msg, Throwable t) {
log(I2PAppContext.getGlobalContext(), Log.ERROR, msg, t);
}
/** @since 0.9.8 */ /** @since 0.9.8 */
private static void info(I2PAppContext ctx, String msg) { private static void info(I2PAppContext ctx, String msg) {
log(ctx, Log.INFO, msg, null); log(ctx, Log.INFO, msg, null);

View File

@ -0,0 +1,103 @@
package net.i2p.crypto;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Locale;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.security.auth.x500.X500Principal;
import net.i2p.I2PAppContext;
import net.i2p.data.Base64;
import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream;
/**
* Java X.509 certificate utilities, consolidated from various places.
*
* @since 0.9.9
*/
public class CertUtil {
private static final int LINE_LENGTH = 64;
/**
* Modified from:
* http://www.exampledepot.com/egs/java.security.cert/ExportCert.html
*
* This method writes a certificate to a file in base64 format.
*
* @return success
* @since 0.8.2, moved from SSLEepGet in 0.9.9
*/
public static boolean saveCert(Certificate cert, File file) {
OutputStream os = null;
try {
// Get the encoded form which is suitable for exporting
byte[] buf = cert.getEncoded();
os = new SecureFileOutputStream(file);
PrintWriter wr = new PrintWriter(os);
wr.println("-----BEGIN CERTIFICATE-----");
String b64 = Base64.encode(buf, true); // true = use standard alphabet
for (int i = 0; i < b64.length(); i += LINE_LENGTH) {
wr.println(b64.substring(i, Math.min(i + LINE_LENGTH, b64.length())));
}
wr.println("-----END CERTIFICATE-----");
wr.flush();
return true;
} catch (CertificateEncodingException cee) {
error("Error writing X509 Certificate " + file.getAbsolutePath(), cee);
return false;
} catch (IOException ioe) {
error("Error writing X509 Certificate " + file.getAbsolutePath(), ioe);
return false;
} finally {
try { if (os != null) os.close(); } catch (IOException foo) {}
}
}
/**
* Get a value out of the subject distinguished name
* @param type e.g. "CN"
* @return value or null if not found
*/
public static String getSubjectValue(X509Certificate cert, String type) {
type = type.toUpperCase(Locale.US);
X500Principal p = cert.getSubjectX500Principal();
String subj = p.getName();
try {
LdapName name = new LdapName(subj);
for (Rdn rdn : name.getRdns()) {
if (type.equals(rdn.getType().toUpperCase(Locale.US)))
return (String) rdn.getValue();
}
} catch (InvalidNameException ine) {}
return null;
}
private static void error(String msg, Throwable t) {
log(I2PAppContext.getGlobalContext(), Log.ERROR, msg, t);
}
private static void error(I2PAppContext ctx, String msg, Throwable t) {
log(ctx, Log.ERROR, msg, t);
}
private static void log(I2PAppContext ctx, int level, String msg, Throwable t) {
Log l = ctx.logManager().getLog(CertUtil.class);
l.log(level, msg, t);
}
}

View File

@ -30,6 +30,7 @@ package net.i2p.crypto;
*/ */
import java.math.BigInteger; import java.math.BigInteger;
import java.security.spec.DSAParameterSpec;
import net.i2p.util.NativeBigInteger; import net.i2p.util.NativeBigInteger;
@ -63,4 +64,9 @@ public class CryptoConstants {
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16); + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16);
public static final BigInteger elgg = new NativeBigInteger("2"); public static final BigInteger elgg = new NativeBigInteger("2");
/**
* @since 0.9.9
*/
public static final DSAParameterSpec DSA_SHA1_SPEC = new DSAParameterSpec(dsap, dsaq, dsag);
} }

View File

@ -34,13 +34,14 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.spec.DSAPrivateKeySpec; import java.security.interfaces.DSAKey;
import java.security.spec.DSAPublicKeySpec; import java.security.interfaces.ECKey;
import java.security.spec.KeySpec; import java.security.interfaces.RSAKey;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.Hash; import net.i2p.data.Hash;
@ -62,6 +63,12 @@ import net.i2p.util.NativeBigInteger;
* *
* Params and rv's changed from Hash to SHA1Hash for version 0.8.1 * Params and rv's changed from Hash to SHA1Hash for version 0.8.1
* Hash variants of sign() and verifySignature() restored in 0.8.3, required by Syndie. * Hash variants of sign() and verifySignature() restored in 0.8.3, required by Syndie.
*
* As of 0.9.9, certain methods support ECDSA keys and signatures, i.e. all types
* specified in SigType. The type is specified by the getType() method in
* Signature, SigningPublicKey, and SigningPrivateKey. See Javadocs for individual
* methods for the supported types. Methods encountering an unsupported type
* will throw an IllegalArgumentException.
*/ */
public class DSAEngine { public class DSAEngine {
private final Log _log; private final Log _log;
@ -80,11 +87,26 @@ public class DSAEngine {
} }
/** /**
* Verify using DSA-SHA1. * Verify using DSA-SHA1 or ECDSA.
* Uses TheCrypto code unless configured to use the java.security libraries. * Uses TheCrypto code for DSA-SHA1 unless configured to use the java.security libraries.
*/ */
public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) { public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
boolean rv; boolean rv;
SigType type = signature.getType();
if (type != verifyingKey.getType())
throw new IllegalArgumentException("type mismatch sig=" + signature.getType() + " key=" + verifyingKey.getType());
if (type != SigType.DSA_SHA1) {
try {
rv = altVerifySig(signature, signedData, verifyingKey);
if ((!rv) && _log.shouldLog(Log.WARN))
_log.warn(type + " Sig Verify Fail");
return rv;
} catch (GeneralSecurityException gse) {
if (_log.shouldLog(Log.WARN))
_log.warn(type + " Sig Verify Fail", gse);
return false;
}
}
if (_useJavaLibs) { if (_useJavaLibs) {
try { try {
rv = altVerifySigSHA1(signature, signedData, verifyingKey); rv = altVerifySigSHA1(signature, signedData, verifyingKey);
@ -104,25 +126,29 @@ public class DSAEngine {
} }
/** /**
* Verify using DSA-SHA1 * Verify using DSA-SHA1 ONLY
*/ */
public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) { public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
return verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey); return verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
} }
/** /**
* Verify using DSA-SHA1 * Verify using DSA-SHA1 ONLY
*/ */
public boolean verifySignature(Signature signature, InputStream in, SigningPublicKey verifyingKey) { public boolean verifySignature(Signature signature, InputStream in, SigningPublicKey verifyingKey) {
return verifySignature(signature, calculateHash(in), verifyingKey); return verifySignature(signature, calculateHash(in), verifyingKey);
} }
/** @param hash SHA-1 hash, NOT a SHA-256 hash */ /**
* Verify using DSA-SHA1 ONLY
* @param hash SHA-1 hash, NOT a SHA-256 hash
*/
public boolean verifySignature(Signature signature, SHA1Hash hash, SigningPublicKey verifyingKey) { public boolean verifySignature(Signature signature, SHA1Hash hash, SigningPublicKey verifyingKey) {
return verifySig(signature, hash, verifyingKey); return verifySig(signature, hash, verifyingKey);
} }
/** /**
* Nonstandard.
* Used by Syndie. * Used by Syndie.
* @since 0.8.3 (restored, was removed in 0.8.1 and 0.8.2) * @since 0.8.3 (restored, was removed in 0.8.1 and 0.8.2)
*/ */
@ -131,10 +157,58 @@ public class DSAEngine {
} }
/** /**
* Generic signature type.
*
* @param hash SHA1Hash, Hash, Hash384, or Hash512
* @since 0.9.9
*/
public boolean verifySignature(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey) {
SigType type = signature.getType();
if (type != verifyingKey.getType())
throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
int hashlen = type.getHashLen();
if (hash.length() != hashlen)
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " sig=" + type);
if (type == SigType.DSA_SHA1)
return verifySig(signature, hash, verifyingKey);
try {
return altVerifySigRaw(signature, hash, verifyingKey);
} catch (GeneralSecurityException gse) {
if (_log.shouldLog(Log.WARN))
_log.warn(type + " Sig Verify Fail", gse);
return false;
}
}
/**
* Generic signature type.
* If you have a Java pubkey, use this, so you don't lose the key parameters,
* which may be different than the ones defined in SigType.
*
* @param hash SHA1Hash, Hash, Hash384, or Hash512
* @param pubKey Java key
* @since 0.9.9
*/
public boolean verifySignature(Signature signature, SimpleDataStructure hash, PublicKey pubKey) {
try {
return altVerifySigRaw(signature, hash, pubKey);
} catch (GeneralSecurityException gse) {
if (_log.shouldLog(Log.WARN))
_log.warn(signature.getType() + " Sig Verify Fail", gse);
return false;
}
}
/**
* Verify using DSA-SHA1 or Syndie DSA-SHA256 ONLY.
* @param hash either a Hash or a SHA1Hash * @param hash either a Hash or a SHA1Hash
* @since 0.8.3 * @since 0.8.3
*/ */
private boolean verifySig(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey) { private boolean verifySig(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey) {
if (signature.getType() != SigType.DSA_SHA1)
throw new IllegalArgumentException("Bad sig type " + signature.getType());
if (verifyingKey.getType() != SigType.DSA_SHA1)
throw new IllegalArgumentException("Bad key type " + verifyingKey.getType());
long start = _context.clock().now(); long start = _context.clock().now();
try { try {
@ -184,10 +258,22 @@ public class DSAEngine {
} }
/** /**
* Sign using DSA-SHA1. * Sign using DSA-SHA1 or ECDSA.
* Uses TheCrypto code unless configured to use the java.security libraries. * Uses TheCrypto code unless configured to use the java.security libraries.
*
* @return null on error
*/ */
public Signature sign(byte data[], SigningPrivateKey signingKey) { public Signature sign(byte data[], SigningPrivateKey signingKey) {
SigType type = signingKey.getType();
if (type != SigType.DSA_SHA1) {
try {
return altSign(data, signingKey);
} catch (GeneralSecurityException gse) {
if (_log.shouldLog(Log.WARN))
_log.warn(type + " Sign Fail", gse);
return null;
}
}
if (_useJavaLibs) { if (_useJavaLibs) {
try { try {
return altSignSHA1(data, signingKey); return altSignSHA1(data, signingKey);
@ -201,7 +287,9 @@ public class DSAEngine {
} }
/** /**
* Sign using DSA-SHA1 * Sign using DSA-SHA1 ONLY
*
* @return null on error
*/ */
public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) { public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
if ((signingKey == null) || (data == null) || (data.length <= 0)) return null; if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
@ -210,8 +298,10 @@ public class DSAEngine {
} }
/** /**
* Sign using DSA-SHA1. * Sign using DSA-SHA1 ONLY.
* Reads the stream until EOF. Does not close the stream. * Reads the stream until EOF. Does not close the stream.
*
* @return null on error
*/ */
public Signature sign(InputStream in, SigningPrivateKey signingKey) { public Signature sign(InputStream in, SigningPrivateKey signingKey) {
if ((signingKey == null) || (in == null) ) return null; if ((signingKey == null) || (in == null) ) return null;
@ -219,13 +309,21 @@ public class DSAEngine {
return sign(h, signingKey); return sign(h, signingKey);
} }
/** @param hash SHA-1 hash, NOT a SHA-256 hash */ /**
* Sign using DSA-SHA1 ONLY.
*
* @param hash SHA-1 hash, NOT a SHA-256 hash
* @return null on error
*/
public Signature sign(SHA1Hash hash, SigningPrivateKey signingKey) { public Signature sign(SHA1Hash hash, SigningPrivateKey signingKey) {
return signIt(hash, signingKey); return signIt(hash, signingKey);
} }
/** /**
* Nonstandard.
* Used by Syndie. * Used by Syndie.
*
* @return null on error
* @since 0.8.3 (restored, was removed in 0.8.1 and 0.8.2) * @since 0.8.3 (restored, was removed in 0.8.1 and 0.8.2)
*/ */
public Signature sign(Hash hash, SigningPrivateKey signingKey) { public Signature sign(Hash hash, SigningPrivateKey signingKey) {
@ -233,11 +331,64 @@ public class DSAEngine {
} }
/** /**
* Generic signature type.
*
* @param hash SHA1Hash, Hash, Hash384, or Hash512
* @return null on error
* @since 0.9.9
*/
public Signature sign(SimpleDataStructure hash, SigningPrivateKey signingKey) {
SigType type = signingKey.getType();
int hashlen = type.getHashLen();
if (hash.length() != hashlen)
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
if (type == SigType.DSA_SHA1)
return signIt(hash, signingKey);
try {
return altSignRaw(hash, signingKey);
} catch (GeneralSecurityException gse) {
if (_log.shouldLog(Log.WARN))
_log.warn(type + " Sign Fail", gse);
return null;
}
}
/**
* Generic signature type.
* If you have a Java privkey, use this, so you don't lose the key parameters,
* which may be different than the ones defined in SigType.
*
* @param hash SHA1Hash, Hash, Hash384, or Hash512
* @param privKey Java key
* @param type returns a Signature of this type
* @return null on error
* @since 0.9.9
*/
public Signature sign(SimpleDataStructure hash, PrivateKey privKey, SigType type) {
String algo = getRawAlgo(privKey);
String talgo = getRawAlgo(type);
if (!algo.equals(talgo))
throw new IllegalArgumentException("type mismatch type=" + type + " key=" + privKey.getClass().getSimpleName());
try {
return altSignRaw(algo, hash, privKey, type);
} catch (GeneralSecurityException gse) {
if (_log.shouldLog(Log.WARN))
_log.warn(type + " Sign Fail", gse);
return null;
}
}
/**
* Sign using DSA-SHA1 or Syndie DSA-SHA256 ONLY.
*
* @param hash either a Hash or a SHA1Hash * @param hash either a Hash or a SHA1Hash
* @return null on error
* @since 0.8.3 * @since 0.8.3
*/ */
private Signature signIt(SimpleDataStructure hash, SigningPrivateKey signingKey) { private Signature signIt(SimpleDataStructure hash, SigningPrivateKey signingKey) {
if ((signingKey == null) || (hash == null)) return null; if ((signingKey == null) || (hash == null)) return null;
if (signingKey.getType() != SigType.DSA_SHA1)
throw new IllegalArgumentException("Bad key type " + signingKey.getType());
long start = _context.clock().now(); long start = _context.clock().now();
Signature sig = new Signature(); Signature sig = new Signature();
@ -275,8 +426,11 @@ public class DSAEngine {
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
out[i] = rbytes[i + 1]; out[i] = rbytes[i + 1];
} }
} else if (rbytes.length > 21) {
_log.error("Bad R length " + rbytes.length);
return null;
} else { } else {
if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short rbytes.length [" + rbytes.length + "]"); //if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short rbytes.length [" + rbytes.length + "]");
//System.arraycopy(rbytes, 0, out, 20 - rbytes.length, rbytes.length); //System.arraycopy(rbytes, 0, out, 20 - rbytes.length, rbytes.length);
for (int i = 0; i < rbytes.length; i++) for (int i = 0; i < rbytes.length; i++)
out[i + 20 - rbytes.length] = rbytes[i]; out[i + 20 - rbytes.length] = rbytes[i];
@ -291,8 +445,11 @@ public class DSAEngine {
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
out[i + 20] = sbytes[i + 1]; out[i + 20] = sbytes[i + 1];
} }
} else if (sbytes.length > 21) {
_log.error("Bad S length " + sbytes.length);
return null;
} else { } else {
if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short sbytes.length [" + sbytes.length + "]"); //if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short sbytes.length [" + sbytes.length + "]");
//System.arraycopy(sbytes, 0, out, 40 - sbytes.length, sbytes.length); //System.arraycopy(sbytes, 0, out, 40 - sbytes.length, sbytes.length);
for (int i = 0; i < sbytes.length; i++) for (int i = 0; i < sbytes.length; i++)
out[i + 20 + 20 - sbytes.length] = sbytes[i]; out[i + 20 + 20 - sbytes.length] = sbytes[i];
@ -337,6 +494,66 @@ public class DSAEngine {
return new SHA1Hash(digested); return new SHA1Hash(digested);
} }
/**
* Generic verify DSA_SHA1, ECDSA, or RSA
* @throws GeneralSecurityException if algorithm unvailable or on other errors
* @since 0.9.9
*/
private boolean altVerifySig(Signature signature, byte[] data, SigningPublicKey verifyingKey)
throws GeneralSecurityException {
SigType type = signature.getType();
if (type != verifyingKey.getType())
throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
if (type == SigType.DSA_SHA1)
return altVerifySigSHA1(signature, data, verifyingKey);
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
jsig.initVerify(pubKey);
jsig.update(data);
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
return rv;
}
/**
* Generic raw verify any type
* @throws GeneralSecurityException if algorithm unvailable or on other errors
* @since 0.9.9
*/
private boolean altVerifySigRaw(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey)
throws GeneralSecurityException {
SigType type = signature.getType();
if (type != verifyingKey.getType())
throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
return verifySignature(signature, hash, pubKey);
}
/**
* Generic raw verify any type.
* If you have a Java pubkey, use this, so you don't lose the key parameters,
* which may be different than the ones defined in SigType.
*
* @throws GeneralSecurityException if algorithm unvailable or on other errors
* @param verifyingKey Java key
* @since 0.9.9
*/
private boolean altVerifySigRaw(Signature signature, SimpleDataStructure hash, PublicKey pubKey)
throws GeneralSecurityException {
SigType type = signature.getType();
int hashlen = hash.length();
if (type.getHashLen() != hashlen)
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
String algo = getRawAlgo(type);
java.security.Signature jsig = java.security.Signature.getInstance(algo);
jsig.initVerify(pubKey);
jsig.update(hash.getData());
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
return rv;
}
/** /**
* Alternate to verifySignature() using java.security libraries. * Alternate to verifySignature() using java.security libraries.
* @throws GeneralSecurityException if algorithm unvailable or on other errors * @throws GeneralSecurityException if algorithm unvailable or on other errors
@ -344,16 +561,10 @@ public class DSAEngine {
*/ */
private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey) throws GeneralSecurityException { private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey) throws GeneralSecurityException {
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA"); java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
KeyFactory keyFact = KeyFactory.getInstance("DSA"); PublicKey pubKey = SigUtil.toJavaDSAKey(verifyingKey);
// y p q g
KeySpec spec = new DSAPublicKeySpec(new NativeBigInteger(1, verifyingKey.getData()),
CryptoConstants.dsap,
CryptoConstants.dsaq,
CryptoConstants.dsag);
PublicKey pubKey = keyFact.generatePublic(spec);
jsig.initVerify(pubKey); jsig.initVerify(pubKey);
jsig.update(data); jsig.update(data);
boolean rv = jsig.verify(sigBytesToASN1(signature.getData())); boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
//if (!rv) { //if (!rv) {
// System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData())); // System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData()));
// System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(sigBytesToASN1(signature.getData()))); // System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(sigBytesToASN1(signature.getData())));
@ -361,6 +572,56 @@ public class DSAEngine {
return rv; return rv;
} }
/**
* Generic sign DSA_SHA1, ECDSA, or RSA
* @throws GeneralSecurityException if algorithm unvailable or on other errors
* @since 0.9.9
*/
private Signature altSign(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
SigType type = privateKey.getType();
if (type == SigType.DSA_SHA1)
return altSignSHA1(data, privateKey);
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
PrivateKey privKey = SigUtil.toJavaKey(privateKey);
jsig.initSign(privKey, _context.random());
jsig.update(data);
return SigUtil.fromJavaSig(jsig.sign(), type);
}
/**
* Generic raw verify any type
* @param hash SHA1Hash, Hash, Hash384, or Hash512
* @throws GeneralSecurityException if algorithm unvailable or on other errors
* @since 0.9.9
*/
private Signature altSignRaw(SimpleDataStructure hash, SigningPrivateKey privateKey) throws GeneralSecurityException {
SigType type = privateKey.getType();
String algo = getRawAlgo(type);
java.security.Signature jsig = java.security.Signature.getInstance(algo);
PrivateKey privKey = SigUtil.toJavaKey(privateKey);
return altSignRaw(algo, hash, privKey, type);
}
/**
* Generic raw verify any type
* @param hash SHA1Hash, Hash, Hash384, or Hash512
* @param type returns a Signature of this type
* @throws GeneralSecurityException if algorithm unvailable or on other errors
* @since 0.9.9
*/
private Signature altSignRaw(String algo, SimpleDataStructure hash, PrivateKey privKey, SigType type)
throws GeneralSecurityException {
int hashlen = hash.length();
if (type.getHashLen() != hashlen)
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
java.security.Signature jsig = java.security.Signature.getInstance(algo);
jsig.initSign(privKey, _context.random());
jsig.update(hash.getData());
return SigUtil.fromJavaSig(jsig.sign(), type);
}
/** /**
* Alternate to sign() using java.security libraries. * Alternate to sign() using java.security libraries.
* @throws GeneralSecurityException if algorithm unvailable or on other errors * @throws GeneralSecurityException if algorithm unvailable or on other errors
@ -368,90 +629,35 @@ public class DSAEngine {
*/ */
private Signature altSignSHA1(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException { private Signature altSignSHA1(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA"); java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
KeyFactory keyFact = KeyFactory.getInstance("DSA"); PrivateKey privKey = SigUtil.toJavaDSAKey(privateKey);
// y p q g
KeySpec spec = new DSAPrivateKeySpec(new NativeBigInteger(1, privateKey.getData()),
CryptoConstants.dsap,
CryptoConstants.dsaq,
CryptoConstants.dsag);
PrivateKey privKey = keyFact.generatePrivate(spec);
jsig.initSign(privKey, _context.random()); jsig.initSign(privKey, _context.random());
jsig.update(data); jsig.update(data);
return new Signature(aSN1ToSigBytes(jsig.sign())); return SigUtil.fromJavaSig(jsig.sign(), SigType.DSA_SHA1);
} }
/** /** @since 0.9.9 */
* http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html private static String getRawAlgo(SigType type) {
* Signature Format ASN.1 sequence of two INTEGER values: r and s, in that order: switch (type.getBaseAlgorithm()) {
* SEQUENCE ::= { r INTEGER, s INTEGER } case DSA:
* return "NONEwithDSA";
* http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One case EC:
* 30 -- tag indicating SEQUENCE return "NONEwithECDSA";
* xx - length in octets case RSA:
* return "NONEwithRSA";
* 02 -- tag indicating INTEGER default:
* xx - length in octets throw new IllegalArgumentException();
* xxxxxx - value }
*
* Convert to BigInteger and back so we have the minimum length representation, as required.
* r and s are always non-negative.
*
* @since 0.8.7
*/
private static byte[] sigBytesToASN1(byte[] sig) {
//System.out.println("pre TO asn1\n" + net.i2p.util.HexDump.dump(sig));
ByteArrayOutputStream baos = new ByteArrayOutputStream(48);
baos.write(0x30);
baos.write(0); // length to be filled in below
byte[] tmp = new byte[20];
baos.write(2);
System.arraycopy(sig, 0, tmp, 0, 20);
BigInteger r = new BigInteger(1, tmp);
byte[] b = r.toByteArray();
baos.write(b.length);
baos.write(b, 0, b.length);
baos.write(2);
System.arraycopy(sig, 20, tmp, 0, 20);
BigInteger s = new BigInteger(1, tmp);
b = s.toByteArray();
baos.write(b.length);
baos.write(b, 0, b.length);
byte[] rv = baos.toByteArray();
rv[1] = (byte) (rv.length - 2);
//System.out.println("post TO asn1\n" + net.i2p.util.HexDump.dump(rv));
return rv;
} }
/** /** @since 0.9.9 */
* See above. private static String getRawAlgo(Key key) {
* @since 0.8.7 if (key instanceof DSAKey)
*/ return "NONEwithDSA";
private static byte[] aSN1ToSigBytes(byte[] asn) { if (key instanceof ECKey)
//System.out.println("pre from asn1\n" + net.i2p.util.HexDump.dump(asn)); return "NONEwithECDSA";
byte[] rv = new byte[40]; if (key instanceof RSAKey)
int rlen = asn[3]; return "NONEwithRSA";
if ((asn[4] & 0x80) != 0) throw new IllegalArgumentException();
throw new IllegalArgumentException("R is negative");
if (rlen > 21)
throw new IllegalArgumentException("R too big " + rlen);
else if (rlen == 21) {
System.arraycopy(asn, 5, rv, 0, 20);
} else
System.arraycopy(asn, 4, rv, 20 - rlen, rlen);
int slenloc = 25 + rlen - 20;
int slen = asn[slenloc];
if ((asn[slenloc + 1] & 0x80) != 0)
throw new IllegalArgumentException("S is negative");
if (slen > 21)
throw new IllegalArgumentException("S too big " + slen);
else if (slen == 21) {
System.arraycopy(asn, slenloc + 2, rv, 20, 20);
} else
System.arraycopy(asn, slenloc + 1, rv, 40 - slen, slen);
//System.out.println("post from asn1\n" + net.i2p.util.HexDump.dump(rv));
return rv;
} }
//private static final int RUNS = 1000; //private static final int RUNS = 1000;

View File

@ -0,0 +1,62 @@
package net.i2p.crypto;
/*
* free (adj.): unencumbered; not under the control of others
* No warranty of any kind, either expressed or implied.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
/**
* Dumb storage in a directory for testing.
* No sanitization of filenames, unsafe.
*
* @since 0.9.9
*/
class DirKeyRing implements KeyRing {
private final File _base;
public DirKeyRing(File baseDir) {
_base = baseDir;
}
/**
* Cert must be in the file (escaped keyName).crt,
* and have a CN == keyName
*/
public PublicKey getKey(String keyName, String scope, SigType type)
throws GeneralSecurityException, IOException {
String fileName = keyName.replace("@", "_at_").replace("<", "_").replace(">", "_");
File test = new File(fileName);
if (test.getParent() != null)
throw new IOException("bad key name");
File sd = new File(_base, scope);
//File td = new File(sd, Integer.toString(type.getCode()));
File kd = new File(sd, fileName + ".crt");
if (!kd.exists())
return null;
InputStream fis = null;
try {
fis = new FileInputStream(kd);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
cert.checkValidity();
String cn = CertUtil.getSubjectValue(cert, "CN");
if (!keyName.equals(cn))
throw new GeneralSecurityException("CN mismatch: " + cn);
return cert.getPublicKey();
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
}
public void setKey(String keyName, String scope, PublicKey key) {}
}

View File

@ -0,0 +1,337 @@
package net.i2p.crypto;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.AlgorithmParameterGenerator;
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECField;
import java.security.spec.ECFieldFp;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import net.i2p.util.NativeBigInteger;
/**
* Constants for elliptic curves, from NIST FIPS 186-4 (2013) / ANSI X9.62
*
* @since 0.9.9
*/
class ECConstants {
private static final boolean DEBUG = false;
private static void log(String s) {
log(s, null);
}
private static void log(String s, Throwable t) {
if (DEBUG) {
System.out.println("ECConstants: " + s);
if (t != null)
t.printStackTrace();
}
}
private static final boolean BC_AVAILABLE;
static {
boolean loaded;
if (Security.getProvider("BC") == null) {
try {
Class cls = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
Constructor con = cls.getConstructor(new Class[0]);
Provider bc = (Provider)con.newInstance(new Object[0]);
Security.addProvider(bc);
log("Added BC provider");
loaded = true;
} catch (Exception e) {
log("Unable to add BC provider", e);
loaded = false;
}
} else {
log("BC provider already loaded");
loaded = true;
}
BC_AVAILABLE = true;
}
public static boolean isBCAvailable() { return BC_AVAILABLE; }
private static class ECParms {
public final String ps, ns, ss, bs, gxs, gys;
private static final BigInteger A = new NativeBigInteger("-3");
private static final int H = 1;
/**
* P and N in decimal, no spaces;
* Seed, B, Gx, Gy in hex, spaces allowed
*/
public ECParms(String pss, String nss, String sss, String bss, String gxss, String gyss) {
ps = pss; ns = nss; ss = sss; bs = bss; gxs = gxss; gys = gyss;
}
public ECParameterSpec genSpec() {
BigInteger pb = new NativeBigInteger(ps);
BigInteger nb = new NativeBigInteger(ns);
BigInteger sb = new NativeBigInteger(ss.replace(" ", ""), 16);
BigInteger bb = new NativeBigInteger(bs.replace(" ", ""), 16);
BigInteger gxb = new NativeBigInteger(gxs.replace(" ", ""), 16);
BigInteger gyb = new NativeBigInteger(gys.replace(" ", ""), 16);
BigInteger ab = new NativeBigInteger(A.mod(pb));
ECField field = new ECFieldFp(pb);
EllipticCurve curve = new EllipticCurve(field, ab, bb, sb.toByteArray());
ECPoint g = new ECPoint(gxb, gyb);
return new ECParameterSpec(curve, g, nb, H);
}
}
/*
D.1.2 Curves over Prime Fields
For each prime p, a pseudo-random curve
E : y**2 = x**3 -3x +b (mod p)
of prime order n is listed 4. (Thus, for these curves, the cofactor is always h = 1.) The following
parameters are given:
The selection a a = -3 for the coefficient of x was made for reasons of efficiency; see IEEE Std 1363-2000.
* The prime modulus p
* The order n
* The 160-bit input seed SEED to the SHA-1 based algorithm (i.e., the domain parameter
seed)
* The output c of the SHA-1 based algorithm
* The coefficient b (satisfying b**2 c = -27 (mod p))
* The base point x coordinate G x
* The base point y coordinate G y
The integers p and n are given in decimal form; bit strings and field elements are given in
hexadecimal.
*/
/*
D.1.2.1 Curve P-192
p= 6277101735386680763835789423207666416083908700390324961279
n= 6277101735386680763835789423176059013767194773182842284081
SEED = 3045ae6f c8422f64 ed579528 d38120ea e12196d5
c= 3099d2bb bfcb2538 542dcd5f b078b6ef 5f3d6fe2 c745de65
b= 64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1
Gx= 188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012
Gy= 07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811
*/
private static final ECParms PARM_P192 = new ECParms(
// P N Seed B Gx Gy
"6277101735386680763835789423207666416083908700390324961279",
"6277101735386680763835789423176059013767194773182842284081",
"3045ae6f c8422f64 ed579528 d38120ea e12196d5",
"64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1",
"188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012",
"07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811"
);
/*
D.1.2.3 Curve P-256
p=
1157920892103562487626974469494075735300861434152903141955
33631308867097853951
n=
115792089210356248762697446949407573529996955224135760342
422259061068512044369
SEED = c49d3608 86e70493 6a6678e1 139d26b7 819f7e90
c=
7efba166 2985be94 03cb055c 75d4f7e0 ce8d84a9 c5114abc
af317768 0104fa0d
b=
5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6
3bce3c3e 27d2604b
Gx=
6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0
f4a13945 d898c296
Gy=
4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece
cbb64068 37bf51f5
*/
private static final ECParms PARM_P256 = new ECParms(
// P N Seed B Gx Gy
"1157920892103562487626974469494075735300861434152903141955" +
"33631308867097853951",
"115792089210356248762697446949407573529996955224135760342" +
"422259061068512044369",
"c49d3608 86e70493 6a6678e1 139d26b7 819f7e90",
"5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6" +
"3bce3c3e 27d2604b",
"6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0" +
"f4a13945 d898c296",
"4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece" +
"cbb64068 37bf51f5"
);
/*
D.1.2.4 Curve P-384
p=
3940200619639447921227904010014361380507973927046544666794
8293404245721771496870329047266088258938001861606973112319
n=
3940200619639447921227904010014361380507973927046544666794
6905279627659399113263569398956308152294913554433653942643
SEED = a335926a a319a27a 1d00896a 6773a482 7acdac73
c=
79d1e655 f868f02f ff48dcde e14151dd b80643c1 406d0ca1
0dfe6fc5 2009540a 495e8042 ea5f744f 6e184667 cc722483
b=
b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112
0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef
Gx=
aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98
59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7
G y=
3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c
e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f
*/
private static final ECParms PARM_P384 = new ECParms(
// P N Seed B Gx Gy
"3940200619639447921227904010014361380507973927046544666794" +
"8293404245721771496870329047266088258938001861606973112319",
"3940200619639447921227904010014361380507973927046544666794" +
"6905279627659399113263569398956308152294913554433653942643",
"a335926a a319a27a 1d00896a 6773a482 7acdac73",
"b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112" +
"0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef",
"aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98" +
"59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7",
"3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c" +
"e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f"
);
/*
D.1.2.5 Curve P-521
p=
686479766013060971498190079908139321726943530014330540939
446345918554318339765605212255964066145455497729631139148
0858037121987999716643812574028291115057151
n=
686479766013060971498190079908139321726943530014330540939
446345918554318339765539424505774633321719753296399637136
3321113864768612440380340372808892707005449
SEED = d09e8800 291cb853 96cc6717 393284aa a0da64ba
c=
0b4 8bfa5f42 0a349495 39d2bdfc 264eeeeb 077688e4
4fbf0ad8 f6d0edb3 7bd6b533 28100051 8e19f1b9 ffbe0fe9
ed8a3c22 00b8f875 e523868c 70c1e5bf 55bad637
b=
051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b
99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd
3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00
Gx=
c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139
053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127
a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66
Gy=
118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449
579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901
3fad0761 353c7086 a272c240 88be9476 9fd16650
*/
private static final ECParms PARM_P521 = new ECParms(
"686479766013060971498190079908139321726943530014330540939" +
"446345918554318339765605212255964066145455497729631139148" +
"0858037121987999716643812574028291115057151",
"686479766013060971498190079908139321726943530014330540939" +
"446345918554318339765539424505774633321719753296399637136" +
"3321113864768612440380340372808892707005449",
"d09e8800 291cb853 96cc6717 393284aa a0da64ba",
"051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b" +
"99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd" +
"3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00",
"c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139" +
"053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127" +
"a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66",
"118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449" +
"579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901" +
"3fad0761 353c7086 a272c240 88be9476 9fd16650"
);
/**
* Generate a spec from a curve name
* @return null if fail
*/
private static ECParameterSpec genSpec(String name) {
// convert the ECGenParameterSpecs to ECParameterSpecs for several reasons:
// 1) to check availability
// 2) efficiency
// 3) SigUtil must cast the AlgorithmParameterSpec to a ECParameterSpec
// to convert a I2P key to a Java key. Sadly, a ECGenParameterSpec
// is not a ECParameterSpec.
try {
AlgorithmParameters ap;
try {
ap = AlgorithmParameters.getInstance("EC");
} catch (Exception e) {
if (BC_AVAILABLE) {
log("Named curve " + name + " is not available, trying BC", e);
ap = AlgorithmParameters.getInstance("EC", "BC");
log("Fallback to BC worked for named curve " + name);
} else {
throw e;
}
}
ECGenParameterSpec ecgps = new ECGenParameterSpec(name);
ap.init(ecgps);
ECParameterSpec rv = ap.getParameterSpec(ECParameterSpec.class);
log("Named curve " + name + " loaded");
return rv;
} catch (Exception e) {
log("Named curve " + name + " is not available", e);
return null;
}
}
/**
* Tries curve name1, then name2, then creates new from parms.
* @param name2 null to skip
* @param parms null to skip
* @return null if all fail
*/
private static ECParameterSpec genSpec(String name1, String name2, ECParms parms) {
ECParameterSpec rv = genSpec(name1);
if (rv == null && name2 != null) {
rv = genSpec(name2);
if (rv == null && parms != null) {
rv = parms.genSpec();
if (rv != null)
log("Curve " + name2 + " created");
}
}
return rv;
}
// standard curve names
// first is OpenJDK 6/7
// second is BC
public static final ECParameterSpec P192_SPEC = genSpec("secp192r1", "P-192", PARM_P192);
public static final ECParameterSpec P256_SPEC = genSpec("secp256r1", "P-256", PARM_P256);
public static final ECParameterSpec P384_SPEC = genSpec("secp384r1", "P-384", PARM_P384);
public static final ECParameterSpec P521_SPEC = genSpec("secp521r1", "P-521", PARM_P521);
// Koblitz
public static final ECParameterSpec K163_SPEC = genSpec("sect163k1", "K-163", null);
public static final ECParameterSpec K233_SPEC = genSpec("sect233k1", "K-233", null);
public static final ECParameterSpec K283_SPEC = genSpec("sect283k1", "K-283", null);
public static final ECParameterSpec K409_SPEC = genSpec("sect409k1", "K-409", null);
public static final ECParameterSpec K571_SPEC = genSpec("sect571k1", "K-571", null);
}

View File

@ -81,6 +81,7 @@ public class ElGamalEngine {
*/ */
public void shutdown() { public void shutdown() {
_ykgen.shutdown(); _ykgen.shutdown();
SigUtil.clearCaches();
} }
/** /**

View File

@ -10,6 +10,14 @@ package net.i2p.crypto;
*/ */
import java.math.BigInteger; import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.ProviderException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECPoint;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.Hash; import net.i2p.data.Hash;
@ -19,9 +27,17 @@ import net.i2p.data.SessionKey;
import net.i2p.data.SigningPrivateKey; import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey; import net.i2p.data.SigningPublicKey;
import net.i2p.data.SimpleDataStructure; import net.i2p.data.SimpleDataStructure;
import net.i2p.util.Log;
import net.i2p.util.NativeBigInteger; import net.i2p.util.NativeBigInteger;
import net.i2p.util.SystemVersion; import net.i2p.util.SystemVersion;
// main()
import net.i2p.data.DataHelper;
import net.i2p.data.Signature;
import net.i2p.util.Clock;
import net.i2p.util.RandomSource;
/** Define a way of generating asymmetrical key pairs as well as symmetrical keys /** Define a way of generating asymmetrical key pairs as well as symmetrical keys
* @author jrandom * @author jrandom
*/ */
@ -129,14 +145,16 @@ public class KeyGenerator {
SimpleDataStructure[] keys = new SimpleDataStructure[2]; SimpleDataStructure[] keys = new SimpleDataStructure[2];
keys[0] = new PublicKey(); keys[0] = new PublicKey();
keys[1] = new PrivateKey(); keys[1] = new PrivateKey();
byte[] k0 = aalpha.toByteArray();
byte[] k1 = a.toByteArray();
// bigInteger.toByteArray returns SIGNED integers, but since they'return positive, // bigInteger.toByteArray returns SIGNED integers, but since they'return positive,
// signed two's complement is the same as unsigned // signed two's complement is the same as unsigned
keys[0].setData(padBuffer(k0, PublicKey.KEYSIZE_BYTES)); try {
keys[1].setData(padBuffer(k1, PrivateKey.KEYSIZE_BYTES)); keys[0].setData(SigUtil.rectify(aalpha, PublicKey.KEYSIZE_BYTES));
keys[1].setData(SigUtil.rectify(a, PrivateKey.KEYSIZE_BYTES));
} catch (InvalidKeyException ike) {
throw new IllegalArgumentException(ike);
}
return keys; return keys;
} }
@ -149,13 +167,18 @@ public class KeyGenerator {
BigInteger a = new NativeBigInteger(1, priv.toByteArray()); BigInteger a = new NativeBigInteger(1, priv.toByteArray());
BigInteger aalpha = CryptoConstants.elgg.modPow(a, CryptoConstants.elgp); BigInteger aalpha = CryptoConstants.elgg.modPow(a, CryptoConstants.elgp);
PublicKey pub = new PublicKey(); PublicKey pub = new PublicKey();
byte [] pubBytes = aalpha.toByteArray(); try {
pub.setData(padBuffer(pubBytes, PublicKey.KEYSIZE_BYTES)); pub.setData(SigUtil.rectify(aalpha, PublicKey.KEYSIZE_BYTES));
} catch (InvalidKeyException ike) {
throw new IllegalArgumentException(ike);
}
return pub; return pub;
} }
/** Generate a pair of DSA keys, where index 0 is a SigningPublicKey, and /** Generate a pair of DSA keys, where index 0 is a SigningPublicKey, and
* index 1 is a SigningPrivateKey * index 1 is a SigningPrivateKey.
* DSA-SHA1 only.
*
* @return pair of keys * @return pair of keys
*/ */
public Object[] generateSigningKeypair() { public Object[] generateSigningKeypair() {
@ -163,6 +186,8 @@ public class KeyGenerator {
} }
/** /**
* DSA-SHA1 only.
*
* Same as above but different return type * Same as above but different return type
* @since 0.8.7 * @since 0.8.7
*/ */
@ -178,15 +203,69 @@ public class KeyGenerator {
BigInteger y = CryptoConstants.dsag.modPow(x, CryptoConstants.dsap); BigInteger y = CryptoConstants.dsag.modPow(x, CryptoConstants.dsap);
keys[0] = new SigningPublicKey(); keys[0] = new SigningPublicKey();
keys[1] = new SigningPrivateKey(); keys[1] = new SigningPrivateKey();
byte k0[] = padBuffer(y.toByteArray(), SigningPublicKey.KEYSIZE_BYTES); try {
byte k1[] = padBuffer(x.toByteArray(), SigningPrivateKey.KEYSIZE_BYTES); keys[0].setData(SigUtil.rectify(y, SigningPublicKey.KEYSIZE_BYTES));
keys[1].setData(SigUtil.rectify(x, SigningPrivateKey.KEYSIZE_BYTES));
keys[0].setData(k0); } catch (InvalidKeyException ike) {
keys[1].setData(k1); throw new IllegalStateException(ike);
}
return keys; return keys;
} }
/** Convert a SigningPrivateKey to a SigningPublicKey /**
* Generic signature type, supports DSA and ECDSA
* @since 0.9.9
*/
public SimpleDataStructure[] generateSigningKeys(SigType type) throws GeneralSecurityException {
if (type == SigType.DSA_SHA1)
return generateSigningKeys();
KeyPairGenerator kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName());
KeyPair kp;
try {
kpg.initialize(type.getParams(), _context.random());
kp = kpg.generateKeyPair();
} catch (ProviderException pe) {
// java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DOMAIN_PARAMS_INVALID
// This is a RuntimeException, thx Sun
// Fails for P-192 only, on Ubuntu
Log log = _context.logManager().getLog(KeyGenerator.class);
String pname = kpg.getProvider().getName();
if ("BC".equals(pname)) {
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type, pe);
throw new GeneralSecurityException("BC KPG for " + type, pe);
}
if (!ECConstants.isBCAvailable())
throw new GeneralSecurityException(pname + " KPG failed for " + type, pe);
if (log.shouldLog(Log.WARN))
log.warn(pname + " KPG failed for " + type + ", trying BC" /* , pe */ );
try {
kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName(), "BC");
kpg.initialize(type.getParams(), _context.random());
kp = kpg.generateKeyPair();
} catch (ProviderException pe2) {
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type + " also", pe2);
// throw original exception
throw new GeneralSecurityException(pname + " KPG for " + type, pe);
} catch (GeneralSecurityException gse) {
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type + " also", gse);
// throw original exception
throw new GeneralSecurityException(pname + " KPG for " + type, pe);
}
}
java.security.PublicKey pubkey = kp.getPublic();
java.security.PrivateKey privkey = kp.getPrivate();
SimpleDataStructure[] keys = new SimpleDataStructure[2];
keys[0] = SigUtil.fromJavaKey(pubkey, type);
keys[1] = SigUtil.fromJavaKey(privkey, type);
return keys;
}
/** Convert a SigningPrivateKey to a SigningPublicKey.
* DSA-SHA1 only.
*
* @param priv a SigningPrivateKey object * @param priv a SigningPrivateKey object
* @return a SigningPublicKey object * @return a SigningPublicKey object
*/ */
@ -194,27 +273,68 @@ public class KeyGenerator {
BigInteger x = new NativeBigInteger(1, priv.toByteArray()); BigInteger x = new NativeBigInteger(1, priv.toByteArray());
BigInteger y = CryptoConstants.dsag.modPow(x, CryptoConstants.dsap); BigInteger y = CryptoConstants.dsag.modPow(x, CryptoConstants.dsap);
SigningPublicKey pub = new SigningPublicKey(); SigningPublicKey pub = new SigningPublicKey();
byte [] pubBytes = padBuffer(y.toByteArray(), SigningPublicKey.KEYSIZE_BYTES); try {
pub.setData(pubBytes); pub.setData(SigUtil.rectify(y, SigningPublicKey.KEYSIZE_BYTES));
} catch (InvalidKeyException ike) {
throw new IllegalArgumentException(ike);
}
return pub; return pub;
} }
/** public static void main(String args[]) {
* Pad the buffer w/ leading 0s or trim off leading bits so the result is the try {
* given length. main2(args);
*/ } catch (Exception e) {
private final static byte[] padBuffer(byte src[], int length) { e.printStackTrace();
byte buf[] = new byte[length]; }
}
if (src.length > buf.length) // extra bits, chop leading bits public static void main2(String args[]) {
System.arraycopy(src, src.length - buf.length, buf, 0, buf.length); RandomSource.getInstance().nextBoolean();
else if (src.length < buf.length) // short bits, padd w/ 0s try { Thread.sleep(1000); } catch (InterruptedException ie) {}
System.arraycopy(src, 0, buf, buf.length - src.length, src.length); int runs = 200; // warmup
else for (int j = 0; j < 2; j++) {
// eq for (int i = 0; i <= 100; i++) {
System.arraycopy(src, 0, buf, 0, buf.length); SigType type = SigType.getByCode(i);
if (type == null)
break;
try {
System.out.println("Testing " + type);
testSig(type, runs);
} catch (Exception e) {
System.out.println("error testing " + type);
e.printStackTrace();
}
}
runs = 1000;
}
}
return buf; private static void testSig(SigType type, int runs) throws GeneralSecurityException {
byte src[] = new byte[512];
long stime = 0;
long vtime = 0;
SimpleDataStructure keys[] = KeyGenerator.getInstance().generateSigningKeys(type);
//System.out.println("pubkey " + keys[0]);
//System.out.println("privkey " + keys[1]);
for (int i = 0; i < runs; i++) {
RandomSource.getInstance().nextBytes(src);
long start = System.nanoTime();
Signature sig = DSAEngine.getInstance().sign(src, (SigningPrivateKey) keys[1]);
long mid = System.nanoTime();
boolean ok = DSAEngine.getInstance().verifySignature(sig, src, (SigningPublicKey) keys[0]);
long end = System.nanoTime();
stime += mid - start;
vtime += end - mid;
if (!ok)
throw new GeneralSecurityException(type + " V(S(data)) fail");
}
stime /= 1000*1000;
vtime /= 1000*1000;
System.out.println(type + " sign/verify " + runs + " times: " + (vtime+stime) + " ms = " +
(((double) stime) / runs) + " each sign, " +
(((double) vtime) / runs) + " each verify, " +
(((double) (stime + vtime)) / runs) + " s+v");
} }
/****** /******

View File

@ -0,0 +1,36 @@
package net.i2p.crypto;
/*
* free (adj.): unencumbered; not under the control of others
* No warranty of any kind, either expressed or implied.
*/
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
/**
* A backend for storing and retrieving SigningPublicKeys
* to be used for verifying signatures.
*
* @since 0.9.9
*/
public interface KeyRing {
/**
* Get a key.
* Throws on all errors.
* @param scope a domain identifier, indicating router update, reseed, etc.
* @return null if none
*/
public PublicKey getKey(String keyName, String scope, SigType type)
throws GeneralSecurityException, IOException;
/**
* Store a key.
* Throws on all errors.
* @param scope a domain identifier, indicating router update, reseed, etc.
*/
public void setKey(String keyName, String scope, PublicKey key)
throws GeneralSecurityException, IOException;
}

View File

@ -0,0 +1,493 @@
package net.i2p.crypto;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Locale;
import net.i2p.I2PAppContext;
import net.i2p.data.Base32;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.ShellCommand;
import net.i2p.util.SystemVersion;
/**
* Keystore utilities, consolidated from various places.
*
* @since 0.9.9
*/
public class KeyStoreUtil {
public static final String DEFAULT_KEYSTORE_PASSWORD = "changeit";
private static final String DEFAULT_KEY_ALGORITHM = "RSA";
private static final int DEFAULT_KEY_SIZE = 2048;
private static final int DEFAULT_KEY_VALID_DAYS = 3652; // 10 years
/**
* Create a new KeyStore object, and load it from ksFile if it is
* non-null and it exists.
* If ksFile is non-null and it does not exist, create a new empty
* keystore file.
*
* @param ksFile may be null
* @param password may be null
* @return success
*/
public static KeyStore createKeyStore(File ksFile, String password)
throws GeneralSecurityException, IOException {
boolean exists = ksFile != null && ksFile.exists();
char[] pwchars = password != null ? password.toCharArray() : null;
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
if (exists) {
InputStream fis = new FileInputStream(ksFile);
ks.load(fis, pwchars);
}
if (ksFile != null && !exists)
ks.store(new SecureFileOutputStream(ksFile), pwchars);
return ks;
}
/**
* Loads certs from location of javax.net.ssl.keyStore property,
* else from $JAVA_HOME/lib/security/jssacacerts,
* else from $JAVA_HOME/lib/security/cacerts.
*
* @return null on catastrophic failure, returns empty KeyStore if can't load system file
* @since 0.8.2, moved from SSLEepGet.initSSLContext() in 0.9.9
*/
public static KeyStore loadSystemKeyStore() {
KeyStore ks;
try {
ks = KeyStore.getInstance(KeyStore.getDefaultType());
} catch (GeneralSecurityException gse) {
error("Key Store init error", gse);
return null;
}
boolean success = false;
String override = System.getProperty("javax.net.ssl.keyStore");
if (override != null)
success = loadCerts(new File(override), ks);
if (!success) {
if (SystemVersion.isAndroid()) {
// thru API 13. As of API 14 (ICS), the file is gone, but
// ks.load(null, pw) will bring in the default certs?
success = loadCerts(new File(System.getProperty("java.home"), "etc/security/cacerts.bks"), ks);
} else {
success = loadCerts(new File(System.getProperty("java.home"), "lib/security/jssecacerts"), ks);
if (!success)
success = loadCerts(new File(System.getProperty("java.home"), "lib/security/cacerts"), ks);
}
}
if (!success) {
try {
// must be initted
ks.load(null, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
} catch (Exception e) {}
error("All key store loads failed, will only load local certificates", null);
}
return ks;
}
/**
* Load all X509 Certs from a key store File into a KeyStore
* Note that each call reinitializes the KeyStore
*
* @return success
* @since 0.8.2, moved from SSLEepGet in 0.9.9
*/
private static boolean loadCerts(File file, KeyStore ks) {
if (!file.exists())
return false;
InputStream fis = null;
try {
fis = new FileInputStream(file);
// "changeit" is the default password
ks.load(fis, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
info("Certs loaded from " + file);
} catch (GeneralSecurityException gse) {
error("KeyStore load error, no default keys: " + file.getAbsolutePath(), gse);
try {
// not clear if null is allowed for password
ks.load(null, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
} catch (Exception foo) {}
return false;
} catch (IOException ioe) {
error("KeyStore load error, no default keys: " + file.getAbsolutePath(), ioe);
try {
ks.load(null, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
} catch (Exception foo) {}
return false;
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
return true;
}
/**
* Count all X509 Certs in a key store
*
* @return number successfully added
* @since 0.8.2, moved from SSLEepGet in 0.9.9
*/
public static int countCerts(KeyStore ks) {
int count = 0;
try {
for(Enumeration<String> e = ks.aliases(); e.hasMoreElements();) {
String alias = e.nextElement();
if (ks.isCertificateEntry(alias)) {
info("Found cert " + alias);
count++;
}
}
} catch (Exception foo) {}
return count;
}
/**
* Load all X509 Certs from a directory and add them to the
* trusted set of certificates in the key store
*
* @return number successfully added
* @since 0.8.2, moved from SSLEepGet in 0.9.9
*/
public static int addCerts(File dir, KeyStore ks) {
info("Looking for X509 Certificates in " + dir.getAbsolutePath());
int added = 0;
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (!f.isFile())
continue;
// use file name as alias
// https://www.sslshopper.com/ssl-converter.html
// No idea if all these formats can actually be read by CertificateFactory
String alias = f.getName().toLowerCase(Locale.US);
if (alias.endsWith(".crt") || alias.endsWith(".pem") || alias.endsWith(".key") ||
alias.endsWith(".der") || alias.endsWith(".key") || alias.endsWith(".p7b") ||
alias.endsWith(".p7c") || alias.endsWith(".pfx") || alias.endsWith(".p12"))
alias = alias.substring(0, alias.length() - 4);
boolean success = addCert(f, alias, ks);
if (success)
added++;
}
}
}
return added;
}
/**
* Load an X509 Cert from a file and add it to the
* trusted set of certificates in the key store
*
* @return success
* @since 0.8.2, moved from SSLEepGet in 0.9.9
*/
public static boolean addCert(File file, String alias, KeyStore ks) {
InputStream fis = null;
try {
fis = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
info("Read X509 Certificate from " + file.getAbsolutePath() +
" Issuer: " + cert.getIssuerX500Principal() +
"; Valid From: " + cert.getNotBefore() +
" To: " + cert.getNotAfter());
try {
cert.checkValidity();
} catch (CertificateExpiredException cee) {
error("Rejecting expired X509 Certificate: " + file.getAbsolutePath(), cee);
return false;
} catch (CertificateNotYetValidException cnyve) {
error("Rejecting X509 Certificate not yet valid: " + file.getAbsolutePath(), cnyve);
return false;
}
ks.setCertificateEntry(alias, cert);
info("Now trusting X509 Certificate, Issuer: " + cert.getIssuerX500Principal());
} catch (GeneralSecurityException gse) {
error("Error reading X509 Certificate: " + file.getAbsolutePath(), gse);
return false;
} catch (IOException ioe) {
error("Error reading X509 Certificate: " + file.getAbsolutePath(), ioe);
return false;
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
return true;
}
/** 48 char b32 string (30 bytes of entropy) */
public static String randomString() {
I2PAppContext ctx = I2PAppContext.getGlobalContext();
// make a random 48 character password (30 * 8 / 5)
byte[] rand = new byte[30];
ctx.random().nextBytes(rand);
return Base32.encode(rand);
}
/**
* Create a keypair and store it in the keystore at ks, creating it if necessary.
* Use default keystore password, valid days, algorithm, and key size.
*
* Warning, may take a long time.
*
* @param ks path to the keystore
* @param alias the name of the key
* @param cname e.g. randomstuff.console.i2p.net
* @param ou e.g. console
* @param keyPW the key password, must be at least 6 characters
*
* @return success
* @since 0.8.3, consolidated from RouterConsoleRUnner and SSLClientListenerRunner in 0.9.9
*/
public static boolean createKeys(File ks, String alias, String cname, String ou,
String keyPW) {
return createKeys(ks, DEFAULT_KEYSTORE_PASSWORD, alias, cname, ou,
DEFAULT_KEY_VALID_DAYS, DEFAULT_KEY_ALGORITHM, DEFAULT_KEY_SIZE, keyPW);
}
/**
* Create a keypair and store it in the keystore at ks, creating it if necessary.
*
* Warning, may take a long time.
*
* @param ks path to the keystore
* @param ksPW the keystore password
* @param alias the name of the key
* @param cname e.g. randomstuff.console.i2p.net
* @param ou e.g. console
* @param validDays e.g. 3652 (10 years)
* @param keyAlg e.g. DSA , RSA, EC
* @param keySize e.g. 1024
* @param keyPW the key password, must be at least 6 characters
*
* @return success
* @since 0.8.3, consolidated from RouterConsoleRUnner and SSLClientListenerRunner in 0.9.9
*/
public static boolean createKeys(File ks, String ksPW, String alias, String cname, String ou,
int validDays, String keyAlg, int keySize, String keyPW) {
if (ks.exists()) {
try {
if (getCert(ks, ksPW, alias) != null) {
error("Not overwriting key " + alias + ", already exists in " + ks, null);
return false;
}
} catch (Exception e) {
error("Not overwriting key \"" + alias + "\", already exists in " + ks, e);
return false;
}
} else {
File dir = ks.getParentFile();
if (dir != null && !dir.exists()) {
File sdir = new SecureDirectory(dir.getAbsolutePath());
if (!sdir.mkdir()) {
error("Can't create directory " + dir, null);
return false;
}
}
}
String keytool = (new File(System.getProperty("java.home"), "bin/keytool")).getAbsolutePath();
String[] args = new String[] {
keytool,
"-genkey", // -genkeypair preferred in newer keytools, but this works with more
"-storetype", KeyStore.getDefaultType(),
"-keystore", ks.getAbsolutePath(),
"-storepass", ksPW,
"-alias", alias,
"-dname", "CN=" + cname + ",OU=" + ou + ",O=I2P Anonymous Network,L=XX,ST=XX,C=XX",
"-validity", Integer.toString(validDays), // 10 years
"-keyalg", keyAlg,
"-sigalg", getSigAlg(keySize, keyAlg),
"-keysize", Integer.toString(keySize),
"-keypass", keyPW
};
// TODO pipe key password to process; requires ShellCommand enhancements
boolean success = (new ShellCommand()).executeSilentAndWaitTimed(args, 240);
if (success) {
success = ks.exists();
if (success) {
try {
success = getPrivateKey(ks, ksPW, alias, keyPW) != null;
if (!success)
error("Key gen failed to get private key", null);
} catch (Exception e) {
error("Key gen failed to get private key", e);
success = false;
}
}
if (!success)
error("Key gen failed for unknown reasons", null);
}
if (success) {
SecureFileOutputStream.setPerms(ks);
info("Created self-signed certificate for " + cname + " in keystore: " + ks.getAbsolutePath());
} else {
StringBuilder buf = new StringBuilder(256);
for (int i = 0; i < args.length; i++) {
buf.append('"').append(args[i]).append("\" ");
}
error("Failed to generate keys using command line: " + buf, null);
}
return success;
}
private static String getSigAlg(int size, String keyalg) {
if (keyalg.equals("EC"))
keyalg = "ECDSA";
String hash;
if (keyalg.equals("ECDSA")) {
if (size <= 256)
hash = "SHA256";
else if (size <= 384)
hash = "SHA384";
else
hash = "SHA512";
} else {
if (size <= 1024)
hash = "SHA1";
else if (size <= 2048)
hash = "SHA256";
else if (size <= 3072)
hash = "SHA384";
else
hash = "SHA512";
}
return hash + "with" + keyalg;
}
/**
* Get a private key out of a keystore
*
* @param ks path to the keystore
* @param ksPW the keystore password, may be null
* @param alias the name of the key
* @param keyPW the key password, must be at least 6 characters
* @return the key or null if not found
*/
public static PrivateKey getPrivateKey(File ks, String ksPW, String alias, String keyPW)
throws GeneralSecurityException, IOException {
InputStream fis = null;
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
fis = new FileInputStream(ks);
char[] pwchars = ksPW != null ? ksPW.toCharArray() : null;
keyStore.load(fis, pwchars);
char[] keypwchars = keyPW.toCharArray();
return (PrivateKey) keyStore.getKey(alias, keypwchars);
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
}
/**
* Get a cert out of a keystore
*
* @param ks path to the keystore
* @param ksPW the keystore password, may be null
* @param alias the name of the key
* @return the certificate or null if not found
*/
public static Certificate getCert(File ks, String ksPW, String alias)
throws GeneralSecurityException, IOException {
InputStream fis = null;
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
fis = new FileInputStream(ks);
char[] pwchars = ksPW != null ? ksPW.toCharArray() : null;
keyStore.load(fis, pwchars);
return keyStore.getCertificate(alias);
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
}
/**
* Pull the cert back OUT of the keystore and save it in Base64-encoded X.509 format
* so the clients can get to it.
*
* @param ks path to the keystore
* @param ksPW the keystore password, may be null
* @param alias the name of the key
* @param certFile output
* @return success
* @since 0.8.3 moved from SSLClientListenerRunner in 0.9.9
*/
public static boolean exportCert(File ks, String ksPW, String alias, File certFile) {
InputStream fis = null;
try {
Certificate cert = getCert(ks, ksPW, alias);
if (cert != null)
return CertUtil.saveCert(cert, certFile);
} catch (GeneralSecurityException gse) {
error("Error saving ASCII SSL keys", gse);
} catch (IOException ioe) {
error("Error saving ASCII SSL keys", ioe);
}
return false;
}
private static void info(String msg) {
log(I2PAppContext.getGlobalContext(), Log.INFO, msg, null);
}
private static void error(String msg, Throwable t) {
log(I2PAppContext.getGlobalContext(), Log.ERROR, msg, t);
}
private static void info(I2PAppContext ctx, String msg) {
log(ctx, Log.INFO, msg, null);
}
private static void error(I2PAppContext ctx, String msg, Throwable t) {
log(ctx, Log.ERROR, msg, t);
}
private static void log(I2PAppContext ctx, int level, String msg, Throwable t) {
if (level >= Log.WARN && !ctx.isRouterContext()) {
System.out.println(msg);
if (t != null)
t.printStackTrace();
}
Log l = ctx.logManager().getLog(KeyStoreUtil.class);
l.log(level, msg, t);
}
public static void main(String[] args) {
try {
if (args.length > 0) {
File ksf = new File(args[0]);
createKeyStore(ksf, DEFAULT_KEYSTORE_PASSWORD);
System.out.println("Created empty keystore " + ksf);
} else {
KeyStore ks = loadSystemKeyStore();
if (ks != null) {
System.out.println("Loaded system keystore");
int count = countCerts(ks);
System.out.println("Found " + count + " certs");
} else {
System.out.println("FAIL");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,29 @@
package net.i2p.crypto;
import java.math.BigInteger;
import java.security.spec.RSAKeyGenParameterSpec;
import net.i2p.util.NativeBigInteger;
/**
* Constants for RSA
*
* @since 0.9.9
*/
class RSAConstants {
/**
* Generate a spec
*/
private static RSAKeyGenParameterSpec genSpec(int size, BigInteger exp) {
return new RSAKeyGenParameterSpec(size, exp);
}
private static final BigInteger F4 = new NativeBigInteger(RSAKeyGenParameterSpec.F4);
// standard specs
public static final RSAKeyGenParameterSpec F4_1024_SPEC = genSpec(1024, F4);
public static final RSAKeyGenParameterSpec F4_2048_SPEC = genSpec(2048, F4);
public static final RSAKeyGenParameterSpec F4_3072_SPEC = genSpec(3072, F4);
public static final RSAKeyGenParameterSpec F4_4096_SPEC = genSpec(4096, F4);
}

View File

@ -26,6 +26,11 @@ public class SHA1Hash extends SimpleDataStructure {
public final static int HASH_LENGTH = SHA1.HASH_LENGTH; public final static int HASH_LENGTH = SHA1.HASH_LENGTH;
/** @since 0.9.9 */
public SHA1Hash() {
super();
}
/** @throws IllegalArgumentException if data is not 20 bytes (null is ok) */ /** @throws IllegalArgumentException if data is not 20 bytes (null is ok) */
public SHA1Hash(byte data[]) { public SHA1Hash(byte data[]) {
super(data); super(data);

View File

@ -11,9 +11,20 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.security.DigestInputStream; import java.security.DigestInputStream;
import java.security.DigestOutputStream; import java.security.DigestOutputStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
@ -21,6 +32,9 @@ import net.i2p.data.DataHelper;
import net.i2p.data.Signature; import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey; import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey; import net.i2p.data.SigningPublicKey;
import net.i2p.data.SimpleDataStructure;
import net.i2p.util.HexDump;
import net.i2p.util.SecureFileOutputStream;
/** /**
* Succesor to the ".sud" format used in TrustedUpdate. * Succesor to the ".sud" format used in TrustedUpdate.
@ -31,60 +45,86 @@ import net.i2p.data.SigningPublicKey;
public class SU3File { public class SU3File {
private final I2PAppContext _context; private final I2PAppContext _context;
private final Map<SigningPublicKey, String> _trustedKeys;
private final File _file; private final File _file;
private String _version; private String _version;
private int _versionLength; private int _versionLength;
private String _signer; private String _signer;
private int _signerLength; private int _signerLength;
private int _contentType; private ContentType _contentType;
private long _contentLength; private long _contentLength;
private SigningPublicKey _signerPubkey; private PublicKey _signerPubkey;
private boolean _headerVerified; private boolean _headerVerified;
private SigType _sigType;
private static final byte[] MAGIC = DataHelper.getUTF8("I2Psu3"); private static final byte[] MAGIC = DataHelper.getUTF8("I2Psu3");
private static final int FILE_VERSION = 0; private static final int FILE_VERSION = 0;
private static final int MIN_VERSION_BYTES = 16; private static final int MIN_VERSION_BYTES = 16;
private static final int VERSION_OFFSET = Signature.SIGNATURE_BYTES; private static final int VERSION_OFFSET = 40; // Signature.SIGNATURE_BYTES; avoid early ctx init
private static final int TYPE_ZIP = 0; private static final int TYPE_ZIP = 0;
private static final int CONTENT_ROUTER = 0; public static final int CONTENT_UNKNOWN = 0;
private static final int CONTENT_ROUTER_P200 = 1; public static final int CONTENT_ROUTER = 1;
private static final int CONTENT_PLUGIN = 2; public static final int CONTENT_PLUGIN = 2;
private static final int CONTENT_RESEED = 3; public static final int CONTENT_RESEED = 3;
private static final int SIG_DSA_160 = SigType.DSA_SHA1.getCode(); private enum ContentType {
UNKNOWN(CONTENT_UNKNOWN, "unknown"),
ROUTER(CONTENT_ROUTER, "router"),
PLUGIN(CONTENT_PLUGIN, "plugin"),
RESEED(CONTENT_RESEED, "reseed")
;
private final int code;
private final String name;
ContentType(int code, String name) {
this.code = code;
this.name = name;
}
public int getCode() { return code; }
public String getName() { return name; }
/** @return null if not supported */
public static ContentType getByCode(int code) {
return BY_CODE.get(Integer.valueOf(code));
}
}
private static final Map<Integer, ContentType> BY_CODE = new HashMap<Integer, ContentType>();
static {
for (ContentType type : ContentType.values()) {
BY_CODE.put(Integer.valueOf(type.getCode()), type);
}
}
private static final ContentType DEFAULT_CONTENT_TYPE = ContentType.UNKNOWN;
// avoid early ctx init
//private static final SigType DEFAULT_SIG_TYPE = SigType.DSA_SHA1;
private static final int DEFAULT_SIG_CODE = 0;
/** /**
* Uses TrustedUpdate's default keys for verification. *
*/ */
public SU3File(String file) { public SU3File(String file) {
this(new File(file)); this(new File(file));
} }
/** /**
* Uses TrustedUpdate's default keys for verification. *
*/ */
public SU3File(File file) { public SU3File(File file) {
this(file, (new TrustedUpdate()).getKeys()); this(I2PAppContext.getGlobalContext(), file);
} }
/** /**
* @param trustedKeys map of pubkey to signer name, null ok if not verifying *
*/ */
public SU3File(File file, Map<SigningPublicKey, String> trustedKeys) { public SU3File(I2PAppContext context, File file) {
this(I2PAppContext.getGlobalContext(), file, trustedKeys);
}
/**
* @param trustedKeys map of pubkey to signer name, null ok if not verifying
*/
public SU3File(I2PAppContext context, File file, Map<SigningPublicKey, String> trustedKeys) {
_context = context; _context = context;
_file = file; _file = file;
_trustedKeys = trustedKeys;
} }
public String getVersionString() throws IOException { public String getVersionString() throws IOException {
@ -97,6 +137,24 @@ public class SU3File {
return _signer; return _signer;
} }
/**
* @return null if unknown
* @since 0.9.9
*/
public SigType getSigType() throws IOException {
verifyHeader();
return _sigType;
}
/**
* @return -1 if unknown
* @since 0.9.9
*/
public int getContentType() throws IOException {
verifyHeader();
return _contentType != null ? _contentType.getCode() : -1;
}
/** /**
* Throws IOE if verify vails. * Throws IOE if verify vails.
*/ */
@ -128,14 +186,13 @@ public class SU3File {
int foo = in.read(); int foo = in.read();
if (foo != FILE_VERSION) if (foo != FILE_VERSION)
throw new IOException("bad file version"); throw new IOException("bad file version");
skip(in, 1); int sigTypeCode = (int) DataHelper.readLong(in, 2);
int sigType = in.read(); _sigType = SigType.getByCode(sigTypeCode);
// TODO, for other known algos we must start over with a new MessageDigest // In verifyAndMigrate it reads this far then rewinds, but we don't need to here
// (rewind 10 bytes) if (_sigType == null)
if (sigType != SIG_DSA_160) throw new IOException("unknown sig type: " + sigTypeCode);
throw new IOException("bad sig type");
_signerLength = (int) DataHelper.readLong(in, 2); _signerLength = (int) DataHelper.readLong(in, 2);
if (_signerLength != Signature.SIGNATURE_BYTES) if (_signerLength != _sigType.getSigLen())
throw new IOException("bad sig length"); throw new IOException("bad sig length");
skip(in, 1); skip(in, 1);
int _versionLength = in.read(); int _versionLength = in.read();
@ -153,9 +210,10 @@ public class SU3File {
if (foo != TYPE_ZIP) if (foo != TYPE_ZIP)
throw new IOException("bad type"); throw new IOException("bad type");
skip(in, 1); skip(in, 1);
_contentType = in.read(); int cType = in.read();
if (_contentType < CONTENT_ROUTER || _contentType > CONTENT_RESEED) _contentType = BY_CODE.get(Integer.valueOf(cType));
throw new IOException("bad content type"); if (_contentType == null)
throw new IOException("unknown content type " + cType);
skip(in, 12); skip(in, 12);
byte[] data = new byte[_versionLength]; byte[] data = new byte[_versionLength];
@ -174,16 +232,18 @@ public class SU3File {
if (bytesRead != signerLen) if (bytesRead != signerLen)
throw new EOFException(); throw new EOFException();
_signer = DataHelper.getUTF8(data); _signer = DataHelper.getUTF8(data);
if (_trustedKeys != null) {
for (Map.Entry<SigningPublicKey, String> e : _trustedKeys.entrySet()) { KeyRing ring = new DirKeyRing(new File(_context.getBaseDir(), "certificates"));
if (e.getValue().equals(_signer)) { try {
_signerPubkey = e.getKey(); _signerPubkey = ring.getKey(_signer, _contentType.getName(), _sigType);
break; } catch (GeneralSecurityException gse) {
} IOException ioe = new IOException("keystore error");
} ioe.initCause(gse);
if (_signerPubkey == null) throw ioe;
throw new IOException("unknown signer: " + _signer);
} }
if (_signerPubkey == null)
throw new IOException("unknown signer: " + _signer);
_headerVerified = true; _headerVerified = true;
} }
@ -200,43 +260,80 @@ public class SU3File {
return VERSION_OFFSET + _versionLength + _signerLength; return VERSION_OFFSET + _versionLength + _signerLength;
} }
/**
* One-pass verify.
* Throws IOE on all format errors.
*
* @return true if signature is good
* @since 0.9.9
*/
public boolean verify() throws IOException {
return verifyAndMigrate(null);
}
/** /**
* One-pass verify and extract the content. * One-pass verify and extract the content.
* Recommend extracting to a temp location as the sig is not checked until * Recommend extracting to a temp location as the sig is not checked until
* after extraction. This will delete the file if the sig does not verify. * after extraction. This will delete the file if the sig does not verify.
* Throws IOE on all format errors. * Throws IOE on all format errors.
* *
* @param migrateTo the output file, probably in zip format * @param migrateTo the output file, probably in zip format. Null for verify only.
* @return true if signature is good * @return true if signature is good
*/ */
public boolean verifyAndMigrate(File migrateTo) throws IOException { public boolean verifyAndMigrate(File migrateTo) throws IOException {
DigestInputStream in = null; InputStream in = null;
OutputStream out = null; OutputStream out = null;
boolean rv = false; boolean rv = false;
try { try {
MessageDigest md = SHA1.getInstance(); in = new BufferedInputStream(new FileInputStream(_file));
in = new DigestInputStream(new BufferedInputStream(new FileInputStream(_file)), md); // read 10 bytes to get the sig type
in.mark(10);
// following is a dup of that in verifyHeader()
byte[] magic = new byte[MAGIC.length];
DataHelper.read(in, magic);
if (!DataHelper.eq(magic, MAGIC))
throw new IOException("Not an su3 file");
skip(in, 1);
int foo = in.read();
if (foo != FILE_VERSION)
throw new IOException("bad file version");
skip(in, 1);
int sigTypeCode = in.read();
_sigType = SigType.getByCode(sigTypeCode);
if (_sigType == null)
throw new IOException("unknown sig type: " + sigTypeCode);
// end duplicate code
// rewind
in.reset();
MessageDigest md = _sigType.getDigestInstance();
DigestInputStream din = new DigestInputStream(in, md);
in = din;
if (!_headerVerified) if (!_headerVerified)
verifyHeader(in); verifyHeader(in);
else else
skip(in, getContentOffset()); skip(in, getContentOffset());
if (_signerPubkey == null) if (_signerPubkey == null)
throw new IOException("unknown signer: " + _signer); throw new IOException("unknown signer: " + _signer);
out = new FileOutputStream(migrateTo); if (migrateTo != null) // else verify only
out = new FileOutputStream(migrateTo);
byte[] buf = new byte[16*1024]; byte[] buf = new byte[16*1024];
long tot = 0; long tot = 0;
while (tot < _contentLength) { while (tot < _contentLength) {
int read = in.read(buf, 0, (int) Math.min(buf.length, _contentLength - tot)); int read = in.read(buf, 0, (int) Math.min(buf.length, _contentLength - tot));
if (read < 0) if (read < 0)
throw new EOFException(); throw new EOFException();
out.write(buf, 0, read); if (migrateTo != null) // else verify only
out.write(buf, 0, read);
tot += read; tot += read;
} }
byte[] sha = md.digest(); byte[] sha = md.digest();
in.on(false); din.on(false);
Signature signature = new Signature(); Signature signature = new Signature(_sigType);
signature.readBytes(in); signature.readBytes(in);
SHA1Hash hash = new SHA1Hash(sha); SimpleDataStructure hash = _sigType.getHashInstance();
hash.setData(sha);
//System.out.println("hash\n" + HexDump.dump(sha));
//System.out.println("sig\n" + HexDump.dump(signature.getData()));
rv = _context.dsa().verifySignature(signature, hash, _signerPubkey); rv = _context.dsa().verifySignature(signature, hash, _signerPubkey);
} catch (DataFormatException dfe) { } catch (DataFormatException dfe) {
IOException ioe = new IOException("foo"); IOException ioe = new IOException("foo");
@ -245,7 +342,7 @@ public class SU3File {
} finally { } finally {
if (in != null) try { in.close(); } catch (IOException ioe) {} if (in != null) try { in.close(); } catch (IOException ioe) {}
if (out != null) try { out.close(); } catch (IOException ioe) {} if (out != null) try { out.close(); } catch (IOException ioe) {}
if (!rv) if (migrateTo != null && !rv)
migrateTo.delete(); migrateTo.delete();
} }
return rv; return rv;
@ -262,20 +359,19 @@ public class SU3File {
* @param signer ID of the public key, 1-255 bytes when converted to UTF-8 * @param signer ID of the public key, 1-255 bytes when converted to UTF-8
*/ */
public void write(File content, int contentType, String version, public void write(File content, int contentType, String version,
String signer, SigningPrivateKey privkey) throws IOException { String signer, PrivateKey privkey, SigType sigType) throws IOException {
InputStream in = null; InputStream in = null;
DigestOutputStream out = null; DigestOutputStream out = null;
boolean ok = false; boolean ok = false;
try { try {
in = new BufferedInputStream(new FileInputStream(content)); in = new BufferedInputStream(new FileInputStream(content));
MessageDigest md = SHA1.getInstance(); MessageDigest md = sigType.getDigestInstance();
out = new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(_file)), md); out = new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(_file)), md);
out.write(MAGIC); out.write(MAGIC);
out.write((byte) 0); out.write((byte) 0);
out.write((byte) FILE_VERSION); out.write((byte) FILE_VERSION);
out.write((byte) 0); DataHelper.writeLong(out, 2, sigType.getCode());
out.write((byte) SIG_DSA_160); DataHelper.writeLong(out, 2, sigType.getSigLen());
DataHelper.writeLong(out, 2, Signature.SIGNATURE_BYTES);
out.write((byte) 0); out.write((byte) 0);
byte[] verBytes = DataHelper.getUTF8(version); byte[] verBytes = DataHelper.getUTF8(version);
if (verBytes.length == 0 || verBytes.length > 255) if (verBytes.length == 0 || verBytes.length > 255)
@ -315,8 +411,13 @@ public class SU3File {
byte[] sha = md.digest(); byte[] sha = md.digest();
out.on(false); out.on(false);
SHA1Hash hash = new SHA1Hash(sha); SimpleDataStructure hash = sigType.getHashInstance();
Signature signature = _context.dsa().sign(hash, privkey); hash.setData(sha);
Signature signature = _context.dsa().sign(hash, privkey, sigType);
if (signature == null)
throw new IOException("sig fail");
//System.out.println("hash\n" + HexDump.dump(sha));
//System.out.println("sig\n" + HexDump.dump(signature.getData()));
signature.writeBytes(out); signature.writeBytes(out);
ok = true; ok = true;
} catch (DataFormatException dfe) { } catch (DataFormatException dfe) {
@ -340,17 +441,46 @@ public class SU3File {
*/ */
public static void main(String[] args) { public static void main(String[] args) {
boolean ok = false; boolean ok = false;
List<String> a = new ArrayList(Arrays.asList(args));
try { try {
if ("showversion".equals(args[0])) { // defaults
ok = showVersionCLI(args[1]); String stype = null;
} else if ("sign".equals(args[0])) { String ctype = null;
ok = signCLI(args[1], args[2], args[3], args[4], args[5]); Iterator<String> iter = a.iterator();
} else if ("verifysig".equals(args[0])) { String cmd = iter.next();
ok = verifySigCLI(args[1]); iter.remove();
for ( ; iter.hasNext(); ) {
String arg = iter.next();
if (arg.equals("-t")) {
iter.remove();
stype = iter.next();
iter.remove();
} else if (arg.equals("-c")) {
iter.remove();
ctype = iter.next();
iter.remove();
}
}
if ("showversion".equals(cmd)) {
ok = showVersionCLI(a.get(0));
} else if ("sign".equals(cmd)) {
// speed things up by specifying a small PRNG buffer size
Properties props = new Properties();
props.setProperty("prng.bufferSize", "16384");
new I2PAppContext(props);
ok = signCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4));
} else if ("verifysig".equals(cmd)) {
ok = verifySigCLI(a.get(0));
} else if ("keygen".equals(cmd)) {
ok = genKeysCLI(stype, a.get(0), a.get(1), a.get(2));
} else if ("extract".equals(cmd)) {
ok = extractCLI(a.get(0), a.get(1));
} else { } else {
showUsageCLI(); showUsageCLI();
} }
} catch (ArrayIndexOutOfBoundsException aioobe) { } catch (NoSuchElementException nsee) {
showUsageCLI();
} catch (IndexOutOfBoundsException ioobe) {
showUsageCLI(); showUsageCLI();
} }
if (!ok) if (!ok)
@ -358,20 +488,85 @@ public class SU3File {
} }
private static final void showUsageCLI() { private static final void showUsageCLI() {
System.err.println("Usage: SU3File showversion signedFile.su3"); System.err.println("Usage: SU3File keygen [-t type|code] publicKeyFile keystore.ks you@mail.i2p");
System.err.println(" SU3File sign inputFile.zip signedFile.su3 privateKeyFile version signerName@mail.i2p"); System.err.println(" SU3File sign [-c type|code] [-t type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p");
System.err.println(" SU3File verifysig signedFile.su3"); System.err.println(" SU3File showversion signedFile.su3");
System.err.println(" SU3File verifysig signedFile.su3");
System.err.println(" SU3File extract signedFile.su3 outFile.zip");
System.err.println(dumpTypes());
}
/** @since 0.9.9 */
private static String dumpTypes() {
StringBuilder buf = new StringBuilder(256);
buf.append("Available signature types:\n");
for (SigType t : EnumSet.allOf(SigType.class)) {
buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')');
if (t.getCode() == DEFAULT_SIG_CODE)
buf.append(" DEFAULT");
buf.append('\n');
}
buf.append("Available content types:\n");
for (ContentType t : EnumSet.allOf(ContentType.class)) {
buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')');
if (t == DEFAULT_CONTENT_TYPE)
buf.append(" DEFAULT");
buf.append('\n');
}
return buf.toString();
}
/**
* @param stype number or name
* @return null if not found
* @since 0.9.9
*/
private static SigType parseSigType(String stype) {
try {
return SigType.valueOf(stype.toUpperCase(Locale.US));
} catch (IllegalArgumentException iae) {
try {
int code = Integer.parseInt(stype);
return SigType.getByCode(code);
} catch (NumberFormatException nfe) {
return null;
}
}
}
/**
* @param stype number or name
* @return null if not found
* @since 0.9.9
*/
private static ContentType parseContentType(String ctype) {
try {
return ContentType.valueOf(ctype.toUpperCase(Locale.US));
} catch (IllegalArgumentException iae) {
try {
int code = Integer.parseInt(ctype);
return ContentType.getByCode(code);
} catch (NumberFormatException nfe) {
return null;
}
}
} }
/** @return success */ /** @return success */
private static final boolean showVersionCLI(String signedFile) { private static final boolean showVersionCLI(String signedFile) {
try { try {
SU3File file = new SU3File(new File(signedFile), null); SU3File file = new SU3File(signedFile);
String versionString = file.getVersionString(); String versionString = file.getVersionString();
if (versionString.equals("")) if (versionString.equals(""))
System.out.println("No version string found in file '" + signedFile + "'"); System.out.println("No version string found in file '" + signedFile + "'");
else else
System.out.println("Version: " + versionString); System.out.println("Version: " + versionString);
String signerString = file.getSignerString();
if (signerString.equals(""))
System.out.println("No signer string found in file '" + signedFile + "'");
else
System.out.println("Signer: " + signerString);
if (file._sigType != null)
System.out.println("SigType: " + file._sigType);
return !versionString.equals(""); return !versionString.equals("");
} catch (IOException ioe) { } catch (IOException ioe) {
ioe.printStackTrace(); ioe.printStackTrace();
@ -379,29 +574,57 @@ public class SU3File {
} }
} }
/** @return success */ /**
private static final boolean signCLI(String inputFile, String signedFile, String privateKeyFile, * @return success
String version, String signerName) { * @since 0.9.9
InputStream in = null; */
private static final boolean signCLI(String stype, String ctype, String inputFile, String signedFile,
String privateKeyFile, String version, String signerName) {
SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : parseSigType(stype);
if (type == null) {
System.out.println("Signature type " + stype + " is not supported");
return false;
}
ContentType ct = ctype == null ? DEFAULT_CONTENT_TYPE : parseContentType(ctype);
if (ct == null) {
System.out.println("Content type " + ctype + " is not supported");
return false;
}
return signCLI(type, ct, inputFile, signedFile, privateKeyFile, version, signerName);
}
/**
* @return success
* @since 0.9.9
*/
private static final boolean signCLI(SigType type, ContentType ctype, String inputFile, String signedFile,
String privateKeyFile, String version, String signerName) {
try { try {
in = new FileInputStream(privateKeyFile); String keypw = "";
SigningPrivateKey spk = new SigningPrivateKey(); while (keypw.length() < 6) {
spk.readBytes(in); System.out.print("Enter password for key \"" + signerName + "\": ");
in.close(); keypw = DataHelper.readLine(System.in).trim();
if (keypw.length() > 0 && keypw.length() < 6)
System.out.println("Key password must be at least 6 characters");
}
File pkfile = new File(privateKeyFile);
PrivateKey pk = KeyStoreUtil.getPrivateKey(pkfile,KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, signerName, keypw);
if (pk == null) {
System.out.println("Private key for " + signerName + " not found in keystore " + privateKeyFile);
return false;
}
SU3File file = new SU3File(signedFile); SU3File file = new SU3File(signedFile);
file.write(new File(inputFile), CONTENT_ROUTER, version, signerName, spk); file.write(new File(inputFile), ctype.getCode(), version, signerName, pk, type);
System.out.println("Input file '" + inputFile + "' signed and written to '" + signedFile + "'"); System.out.println("Input file '" + inputFile + "' signed and written to '" + signedFile + "'");
return true; return true;
} catch (DataFormatException dfe) { } catch (GeneralSecurityException gse) {
System.out.println("Error signing input file '" + inputFile + "'"); System.out.println("Error signing input file '" + inputFile + "'");
dfe.printStackTrace(); gse.printStackTrace();
return false; return false;
} catch (IOException ioe) { } catch (IOException ioe) {
System.out.println("Error signing input file '" + inputFile + "'"); System.out.println("Error signing input file '" + inputFile + "'");
ioe.printStackTrace(); ioe.printStackTrace();
return false; return false;
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
} }
} }
@ -410,11 +633,11 @@ public class SU3File {
InputStream in = null; InputStream in = null;
try { try {
SU3File file = new SU3File(signedFile); SU3File file = new SU3File(signedFile);
boolean isValidSignature = file.verifyAndMigrate(new File("/dev/null")); boolean isValidSignature = file.verify();
if (isValidSignature) if (isValidSignature)
System.out.println("Signature VALID (signed by " + file.getSignerString() + ')'); System.out.println("Signature VALID (signed by " + file.getSignerString() + ' ' + file._sigType + ')');
else else
System.out.println("Signature INVALID (signed by " + file.getSignerString() + ')'); System.out.println("Signature INVALID (signed by " + file.getSignerString() + ' ' + file._sigType +')');
return isValidSignature; return isValidSignature;
} catch (IOException ioe) { } catch (IOException ioe) {
System.out.println("Error verifying input file '" + signedFile + "'"); System.out.println("Error verifying input file '" + signedFile + "'");
@ -422,4 +645,88 @@ public class SU3File {
return false; return false;
} }
} }
/**
* @return success
* @since 0.9.9
*/
private static final boolean extractCLI(String signedFile, String outFile) {
InputStream in = null;
try {
SU3File file = new SU3File(signedFile);
File out = new File(outFile);
boolean ok = file.verifyAndMigrate(out);
if (ok)
System.out.println("File extracted (signed by " + file.getSignerString() + ' ' + file._sigType + ')');
else
System.out.println("Signature INVALID (signed by " + file.getSignerString() + ' ' + file._sigType +')');
return ok;
} catch (IOException ioe) {
System.out.println("Error extracting from file '" + signedFile + "'");
ioe.printStackTrace();
return false;
}
}
/**
* @return success
* @since 0.9.9
*/
private static final boolean genKeysCLI(String stype, String publicKeyFile, String privateKeyFile, String alias) {
SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : parseSigType(stype);
if (type == null) {
System.out.println("Signature type " + stype + " is not supported");
return false;
}
return genKeysCLI(type, publicKeyFile, privateKeyFile, alias);
}
/**
* Writes Java-encoded keys (X.509 for public and PKCS#8 for private)
* @return success
* @since 0.9.9
*/
private static final boolean genKeysCLI(SigType type, String publicKeyFile, String privateKeyFile, String alias) {
File pubFile = new File(publicKeyFile);
if (pubFile.exists()) {
System.out.println("Error: Not overwriting file " + publicKeyFile);
return false;
}
File ksFile = new File(privateKeyFile);
String keypw = "";
try {
while (alias.length() == 0) {
System.out.print("Enter key name (example@mail.i2p): ");
alias = DataHelper.readLine(System.in).trim();
}
while (keypw.length() < 6) {
System.out.print("Enter new key password: ");
keypw = DataHelper.readLine(System.in).trim();
if (keypw.length() > 0 && keypw.length() < 6)
System.out.println("Key password must be at least 6 characters");
}
} catch (IOException ioe) {
return false;
}
int keylen = type.getPubkeyLen() * 8;
if (type.getBaseAlgorithm() == SigAlgo.EC) {
keylen /= 2;
if (keylen == 528)
keylen = 521;
}
boolean success = KeyStoreUtil.createKeys(ksFile, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, alias,
alias, "I2P", 3652, type.getBaseAlgorithm().getName(),
keylen, keypw);
if (!success) {
System.err.println("Error creating keys for " + alias);
return false;
}
File outfile = new File(publicKeyFile);
success = KeyStoreUtil.exportCert(ksFile, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, alias, outfile);
if (!success) {
System.err.println("Error writing public key for " + alias + " to " + outfile);
return false;
}
return true;
}
} }

View File

@ -0,0 +1,22 @@
package net.i2p.crypto;
/**
* Base signature algorithm type
*
* @since 0.9.9
*/
public enum SigAlgo {
DSA("DSA"),
EC("EC"),
RSA("RSA")
;
private final String name;
SigAlgo(String name) {
this.name = name;
}
public String getName() { return name; }
}

View File

@ -7,6 +7,9 @@ import java.security.spec.InvalidParameterSpecException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.i2p.data.Hash;
import net.i2p.data.SimpleDataStructure;
/** /**
* Defines the properties for various signature types * Defines the properties for various signature types
* that I2P supports or may someday support. * that I2P supports or may someday support.
@ -23,22 +26,53 @@ public enum SigType {
* Pubkey 128 bytes; privkey 20 bytes; hash 20 bytes; sig 40 bytes * Pubkey 128 bytes; privkey 20 bytes; hash 20 bytes; sig 40 bytes
* @since 0.9.8 * @since 0.9.8
*/ */
DSA_SHA1(0, 128, 20, 20, 40, "SHA-1", "SHA1withDSA", null), DSA_SHA1(0, 128, 20, 20, 40, SigAlgo.DSA, "SHA-1", "SHA1withDSA", CryptoConstants.DSA_SHA1_SPEC),
/** Pubkey 48 bytes; privkey 24 bytes; hash 20 bytes; sig 48 bytes */
ECDSA_SHA1_P192(1, 48, 24, 20, 48, "SHA-1", "SHA1withECDSA", null),
/** Pubkey 64 bytes; privkey 32 bytes; hash 32 bytes; sig 64 bytes */ /** Pubkey 64 bytes; privkey 32 bytes; hash 32 bytes; sig 64 bytes */
ECDSA_SHA256_P256(2, 64, 32, 32, 64, "SHA-256", "SHA256withECDSA", null), ECDSA_SHA256_P256(1, 64, 32, 32, 64, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.P256_SPEC),
/** Pubkey 96 bytes; privkey 48 bytes; hash 48 bytes; sig 96 bytes */ /** Pubkey 96 bytes; privkey 48 bytes; hash 48 bytes; sig 96 bytes */
ECDSA_SHA384_P384(3, 96, 48, 48, 96, "SHA-384", "SHA384withECDSA", null), ECDSA_SHA384_P384(2, 96, 48, 48, 96, SigAlgo.EC, "SHA-384", "SHA384withECDSA", ECConstants.P384_SPEC),
/** Pubkey 132 bytes; privkey 66 bytes; hash 64 bytes; sig 132 bytes */ /** Pubkey 132 bytes; privkey 66 bytes; hash 64 bytes; sig 132 bytes */
ECDSA_SHA512_P521(4, 132, 66, 64, 132, "SHA-512", "SHA512withECDSA", null), ECDSA_SHA512_P521(3, 132, 66, 64, 132, SigAlgo.EC, "SHA-512", "SHA512withECDSA", ECConstants.P521_SPEC),
/** Pubkey 256 bytes; privkey 512 bytes; hash 32 bytes; sig 256 bytes */
RSA_SHA256_2048(4, 256, 512, 32, 256, SigAlgo.RSA, "SHA-256", "SHA256withRSA", RSAConstants.F4_2048_SPEC),
/** Pubkey 384 bytes; privkey 768 bytes; hash 48 bytes; sig 384 bytes */
RSA_SHA384_3072(5, 384, 768, 48, 384, SigAlgo.RSA, "SHA-384", "SHA384withRSA", RSAConstants.F4_3072_SPEC),
/** Pubkey 512 bytes; privkey 1024 bytes; hash 64 bytes; sig 512 bytes */
RSA_SHA512_4096(6, 512, 1024, 64, 512, SigAlgo.RSA, "SHA-512", "SHA512withRSA", RSAConstants.F4_4096_SPEC),
// TESTING....................
// others..........
// EC mix and match
//ECDSA_SHA256_P192(5, 48, 24, 32, 48, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.P192_SPEC),
//ECDSA_SHA256_P384(6, 96, 48, 32, 96, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.P384_SPEC),
//ECDSA_SHA256_P521(7, 132, 66, 32, 132, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.P521_SPEC),
//ECDSA_SHA384_P256(8, 64, 32, 48, 64, SigAlgo.EC, "SHA-384", "SHA384withECDSA", ECConstants.P256_SPEC),
//ECDSA_SHA384_P521(9, 132, 66, 48, 132, SigAlgo.EC, "SHA-384", "SHA384withECDSA", ECConstants.P521_SPEC),
//ECDSA_SHA512_P256(10, 64, 32, 64, 64, SigAlgo.EC, "SHA-512", "SHA512withECDSA", ECConstants.P256_SPEC),
//ECDSA_SHA512_P384(11, 96, 48, 64, 96, SigAlgo.EC, "SHA-512", "SHA512withECDSA", ECConstants.P384_SPEC),
// Koblitz
//ECDSA_SHA256_K163(12, 42, 21, 32, 42, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K163_SPEC),
//ECDSA_SHA256_K233(13, 60, 30, 32, 60, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K233_SPEC),
//ECDSA_SHA256_K283(14, 72, 36, 32, 72, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K283_SPEC),
//ECDSA_SHA256_K409(15, 104, 52, 32, 104, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K409_SPEC),
//ECDSA_SHA256_K571(16, 144, 72, 32, 144, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K571_SPEC),
// too short..............
/** Pubkey 48 bytes; privkey 24 bytes; hash 20 bytes; sig 48 bytes */
//ECDSA_SHA1_P192(1, 48, 24, 20, 48, SigAlgo.EC, "SHA-1", "SHA1withECDSA", ECConstants.P192_SPEC),
//RSA_SHA1(17, 128, 256, 20, 128, SigAlgo.RSA, "SHA-1", "SHA1withRSA", RSAConstants.F4_1024_SPEC),
//MD5 //MD5
//ELGAMAL_SHA256
//RSA_SHA1 //RSA_SHA1
//RSA_SHA256
//RSA_SHA384 //ELGAMAL_SHA256
//RSA_SHA512
//DSA_2048_224(2, 256, 28, 32, 56, "SHA-256"), //DSA_2048_224(2, 256, 28, 32, 56, "SHA-256"),
// Nonstandard, used by Syndie. // Nonstandard, used by Syndie.
// Pubkey 128 bytes; privkey 20 bytes; hash 32 bytes; sig 40 bytes // Pubkey 128 bytes; privkey 20 bytes; hash 32 bytes; sig 40 bytes
@ -47,19 +81,22 @@ public enum SigType {
//DSA_2048_256(2, 256, 32, 32, 64, "SHA-256", "?"), //DSA_2048_256(2, 256, 32, 32, 64, "SHA-256", "?"),
// Pubkey 384 bytes; privkey 32 bytes; hash 32 bytes; sig 64 bytes // Pubkey 384 bytes; privkey 32 bytes; hash 32 bytes; sig 64 bytes
//DSA_3072_256(3, 384, 32, 32, 64, "SHA-256", "?"), //DSA_3072_256(3, 384, 32, 32, 64, "SHA-256", "?"),
; ;
private final int code, pubkeyLen, privkeyLen, hashLen, sigLen; private final int code, pubkeyLen, privkeyLen, hashLen, sigLen;
private final SigAlgo base;
private final String digestName, algoName; private final String digestName, algoName;
private final AlgorithmParameterSpec params; private final AlgorithmParameterSpec params;
SigType(int cod, int pubLen, int privLen, int hLen, int sLen, SigType(int cod, int pubLen, int privLen, int hLen, int sLen, SigAlgo baseAlgo,
String mdName, String aName, AlgorithmParameterSpec pSpec) { String mdName, String aName, AlgorithmParameterSpec pSpec) {
code = cod; code = cod;
pubkeyLen = pubLen; pubkeyLen = pubLen;
privkeyLen = privLen; privkeyLen = privLen;
hashLen = hLen; hashLen = hLen;
sigLen = sLen; sigLen = sLen;
base = baseAlgo;
digestName = mdName; digestName = mdName;
algoName = aName; algoName = aName;
params = pSpec; params = pSpec;
@ -75,6 +112,8 @@ public enum SigType {
public int getHashLen() { return hashLen; } public int getHashLen() { return hashLen; }
/** the length of the signature, in bytes */ /** the length of the signature, in bytes */
public int getSigLen() { return sigLen; } public int getSigLen() { return sigLen; }
/** the standard base algorithm name used for the Java crypto factories */
public SigAlgo getBaseAlgorithm() { return base; }
/** the standard name used for the Java crypto factories */ /** the standard name used for the Java crypto factories */
public String getAlgorithmName() { return algoName; } public String getAlgorithmName() { return algoName; }
/** /**
@ -100,6 +139,25 @@ public enum SigType {
} }
} }
/**
* @since 0.9.9
* @throws UnsupportedOperationException if not supported
*/
public SimpleDataStructure getHashInstance() {
switch (getHashLen()) {
case 20:
return new SHA1Hash();
case 32:
return new Hash();
case 48:
return new Hash384();
case 64:
return new Hash512();
default:
throw new UnsupportedOperationException("Unsupported hash length: " + getHashLen());
}
}
private static final Map<Integer, SigType> BY_CODE = new HashMap<Integer, SigType>(); private static final Map<Integer, SigType> BY_CODE = new HashMap<Integer, SigType>();
static { static {

View File

@ -0,0 +1,546 @@
package net.i2p.crypto;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.ECField;
import java.security.spec.ECFieldFp;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey;
import net.i2p.util.LHMCache;
import net.i2p.util.NativeBigInteger;
/**
* Utilities for Signing keys and Signatures
*
* @since 0.9.9
*/
class SigUtil {
private static final Map<SigningPublicKey, ECPublicKey> _pubkeyCache = new LHMCache(64);
private static final Map<SigningPrivateKey, ECPrivateKey> _privkeyCache = new LHMCache(16);
private SigUtil() {}
/**
* @return JAVA key!
*/
public static PublicKey toJavaKey(SigningPublicKey pk)
throws GeneralSecurityException {
switch (pk.getType().getBaseAlgorithm()) {
case DSA:
return toJavaDSAKey(pk);
case EC:
return toJavaECKey(pk);
case RSA:
return toJavaRSAKey(pk);
default:
throw new IllegalArgumentException();
}
}
/**
* @return JAVA key!
*/
public static PrivateKey toJavaKey(SigningPrivateKey pk)
throws GeneralSecurityException {
switch (pk.getType().getBaseAlgorithm()) {
case DSA:
return toJavaDSAKey(pk);
case EC:
return toJavaECKey(pk);
case RSA:
return toJavaRSAKey(pk);
default:
throw new IllegalArgumentException();
}
}
/**
* @param pk JAVA key!
*/
public static SigningPublicKey fromJavaKey(PublicKey pk, SigType type)
throws GeneralSecurityException {
switch (type.getBaseAlgorithm()) {
case DSA:
return fromJavaKey((DSAPublicKey) pk);
case EC:
return fromJavaKey((ECPublicKey) pk, type);
case RSA:
return fromJavaKey((RSAPublicKey) pk, type);
default:
throw new IllegalArgumentException();
}
}
/**
* @param pk JAVA key!
*/
public static SigningPrivateKey fromJavaKey(PrivateKey pk, SigType type)
throws GeneralSecurityException {
switch (type.getBaseAlgorithm()) {
case DSA:
return fromJavaKey((DSAPrivateKey) pk);
case EC:
return fromJavaKey((ECPrivateKey) pk, type);
case RSA:
return fromJavaKey((RSAPrivateKey) pk, type);
default:
throw new IllegalArgumentException();
}
}
/**
* @return JAVA key!
*/
public static ECPublicKey toJavaECKey(SigningPublicKey pk)
throws GeneralSecurityException {
ECPublicKey rv;
synchronized (_pubkeyCache) {
rv = _pubkeyCache.get(pk);
}
if (rv != null)
return rv;
rv = cvtToJavaECKey(pk);
synchronized (_pubkeyCache) {
_pubkeyCache.put(pk, rv);
}
return rv;
}
/**
* @return JAVA key!
*/
public static ECPrivateKey toJavaECKey(SigningPrivateKey pk)
throws GeneralSecurityException {
ECPrivateKey rv;
synchronized (_privkeyCache) {
rv = _privkeyCache.get(pk);
}
if (rv != null)
return rv;
rv = cvtToJavaECKey(pk);
synchronized (_privkeyCache) {
_privkeyCache.put(pk, rv);
}
return rv;
}
private static ECPublicKey cvtToJavaECKey(SigningPublicKey pk)
throws GeneralSecurityException {
SigType type = pk.getType();
BigInteger[] xy = split(pk.getData());
ECPoint w = new ECPoint(xy[0], xy[1]);
// see ECConstants re: casting
ECPublicKeySpec ks = new ECPublicKeySpec(w, (ECParameterSpec) type.getParams());
KeyFactory kf = KeyFactory.getInstance("EC");
return (ECPublicKey) kf.generatePublic(ks);
}
public static ECPrivateKey cvtToJavaECKey(SigningPrivateKey pk)
throws GeneralSecurityException {
SigType type = pk.getType();
int len = type.getPubkeyLen();
int sublen = len / 2;
byte[] b = pk.getData();
BigInteger s = new NativeBigInteger(1, b);
// see ECConstants re: casting
ECPrivateKeySpec ks = new ECPrivateKeySpec(s, (ECParameterSpec) type.getParams());
KeyFactory kf = KeyFactory.getInstance("EC");
return (ECPrivateKey) kf.generatePrivate(ks);
}
public static SigningPublicKey fromJavaKey(ECPublicKey pk, SigType type)
throws GeneralSecurityException {
ECPoint w = pk.getW();
BigInteger x = w.getAffineX();
BigInteger y = w.getAffineY();
int len = type.getPubkeyLen();
byte[] b = combine(x, y, len);
return new SigningPublicKey(type, b);
}
public static SigningPrivateKey fromJavaKey(ECPrivateKey pk, SigType type)
throws GeneralSecurityException {
BigInteger s = pk.getS();
int len = type.getPrivkeyLen();
byte[] bs = rectify(s, len);
return new SigningPrivateKey(type, bs);
}
public static DSAPublicKey toJavaDSAKey(SigningPublicKey pk)
throws GeneralSecurityException {
KeyFactory kf = KeyFactory.getInstance("DSA");
// y p q g
KeySpec ks = new DSAPublicKeySpec(new NativeBigInteger(1, pk.getData()),
CryptoConstants.dsap,
CryptoConstants.dsaq,
CryptoConstants.dsag);
return (DSAPublicKey) kf.generatePublic(ks);
}
public static DSAPrivateKey toJavaDSAKey(SigningPrivateKey pk)
throws GeneralSecurityException {
KeyFactory kf = KeyFactory.getInstance("DSA");
// x p q g
KeySpec ks = new DSAPrivateKeySpec(new NativeBigInteger(1, pk.getData()),
CryptoConstants.dsap,
CryptoConstants.dsaq,
CryptoConstants.dsag);
return (DSAPrivateKey) kf.generatePrivate(ks);
}
public static SigningPublicKey fromJavaKey(DSAPublicKey pk)
throws GeneralSecurityException {
BigInteger y = pk.getY();
SigType type = SigType.DSA_SHA1;
int len = type.getPubkeyLen();
byte[] by = rectify(y, len);
return new SigningPublicKey(type, by);
}
public static SigningPrivateKey fromJavaKey(DSAPrivateKey pk)
throws GeneralSecurityException {
BigInteger x = pk.getX();
SigType type = SigType.DSA_SHA1;
int len = type.getPrivkeyLen();
byte[] bx = rectify(x, len);
return new SigningPrivateKey(type, bx);
}
/**
* @deprecated unused
*/
public static RSAPublicKey toJavaRSAKey(SigningPublicKey pk)
throws GeneralSecurityException {
SigType type = pk.getType();
KeyFactory kf = KeyFactory.getInstance("RSA");
BigInteger n = new NativeBigInteger(1, pk.getData());
BigInteger e = ((RSAKeyGenParameterSpec)type.getParams()).getPublicExponent();
// modulus exponent
KeySpec ks = new RSAPublicKeySpec(n, e);
return (RSAPublicKey) kf.generatePublic(ks);
}
/**
* @deprecated unused
*/
public static RSAPrivateKey toJavaRSAKey(SigningPrivateKey pk)
throws GeneralSecurityException {
KeyFactory kf = KeyFactory.getInstance("RSA");
// private key is modulus (pubkey) + exponent
BigInteger[] nd = split(pk.getData());
// modulus exponent
KeySpec ks = new RSAPrivateKeySpec(nd[0], nd[1]);
return (RSAPrivateKey) kf.generatePrivate(ks);
}
/**
* @deprecated unused
*/
public static SigningPublicKey fromJavaKey(RSAPublicKey pk, SigType type)
throws GeneralSecurityException {
BigInteger n = pk.getModulus();
int len = type.getPubkeyLen();
byte[] bn = rectify(n, len);
return new SigningPublicKey(type, bn);
}
/**
* @deprecated unused
*/
public static SigningPrivateKey fromJavaKey(RSAPrivateKey pk, SigType type)
throws GeneralSecurityException {
// private key is modulus (pubkey) + exponent
BigInteger n = pk.getModulus();
BigInteger d = pk.getPrivateExponent();
byte[] b = combine(n, d, type.getPrivkeyLen());
return new SigningPrivateKey(type, b);
}
/**
* @return ASN.1 representation
*/
public static byte[] toJavaSig(Signature sig) {
// RSA sigs are not ASN encoded
if (sig.getType().getBaseAlgorithm() == SigAlgo.RSA)
return sig.getData();
return sigBytesToASN1(sig.getData());
}
/**
* @param asn ASN.1 representation
* @return a Signature with SigType type
*/
public static Signature fromJavaSig(byte[] asn, SigType type)
throws SignatureException {
// RSA sigs are not ASN encoded
if (type.getBaseAlgorithm() == SigAlgo.RSA)
return new Signature(type, asn);
return new Signature(type, aSN1ToSigBytes(asn, type.getSigLen()));
}
/**
* @return JAVA key!
*/
public static PublicKey importJavaPublicKey(File file, SigType type)
throws GeneralSecurityException, IOException {
byte[] data = getData(file);
KeySpec ks = new X509EncodedKeySpec(data);
String algo = type.getBaseAlgorithm().getName();
KeyFactory kf = KeyFactory.getInstance(algo);
return kf.generatePublic(ks);
}
/**
* @return JAVA key!
*/
public static PrivateKey importJavaPrivateKey(File file, SigType type)
throws GeneralSecurityException, IOException {
byte[] data = getData(file);
KeySpec ks = new PKCS8EncodedKeySpec(data);
String algo = type.getBaseAlgorithm().getName();
KeyFactory kf = KeyFactory.getInstance(algo);
return kf.generatePrivate(ks);
}
/** 16 KB max */
private static byte[] getData(File file) throws IOException {
byte buf[] = new byte[1024];
InputStream in = null;
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
try {
in = new FileInputStream(file);
int read = 0;
int tot = 0;
while ( (read = in.read(buf)) != -1) {
out.write(buf, 0, read);
tot += read;
if (tot > 16*1024)
throw new IOException("too big");
}
return out.toByteArray();
} finally {
if (in != null)
try { in.close(); } catch (IOException ioe) {}
}
}
/**
* Split a byte array into two BigIntegers
* @return array of two BigIntegers
*/
private static BigInteger[] split(byte[] b) {
int sublen = b.length / 2;
byte[] bx = new byte[sublen];
byte[] by = new byte[sublen];
System.arraycopy(b, 0, bx, 0, sublen);
System.arraycopy(b, sublen, by, 0, sublen);
NativeBigInteger x = new NativeBigInteger(1, bx);
NativeBigInteger y = new NativeBigInteger(1, by);
return new NativeBigInteger[] {x, y};
}
/**
* Combine two BigIntegers of nominal length = len / 2
* @return array of exactly len bytes
*/
private static byte[] combine(BigInteger x, BigInteger y, int len)
throws InvalidKeyException {
int sublen = len / 2;
byte[] b = new byte[len];
byte[] bx = rectify(x, sublen);
byte[] by = rectify(y, sublen);
System.arraycopy(bx, 0, b, 0, sublen);
System.arraycopy(by, 0, b, sublen, sublen);
return b;
}
/**
* @param bi non-negative
* @return array of exactly len bytes
*/
public static byte[] rectify(BigInteger bi, int len)
throws InvalidKeyException {
byte[] b = bi.toByteArray();
if (b.length == len) {
// just right
return b;
}
if (b.length > len + 1)
throw new InvalidKeyException("key too big (" + b.length + ") max is " + (len + 1));
byte[] rv = new byte[len];
if (b.length == 0)
return rv;
if ((b[0] & 0x80) != 0)
throw new InvalidKeyException("negative");
if (b.length > len) {
// leading 0 byte
if (b[0] != 0)
throw new InvalidKeyException("key too big (" + b.length + ") max is " + len);
System.arraycopy(b, 1, rv, 0, len);
} else {
// smaller
System.arraycopy(b, 0, rv, len - b.length, b.length);
}
return rv;
}
/**
* http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html
* Signature Format ASN.1 sequence of two INTEGER values: r and s, in that order:
* SEQUENCE ::= { r INTEGER, s INTEGER }
*
* http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
* 30 -- tag indicating SEQUENCE
* xx - length in octets
*
* 02 -- tag indicating INTEGER
* xx - length in octets
* xxxxxx - value
*
* Convert to BigInteger and back so we have the minimum length representation, as required.
* r and s are always non-negative.
*
* Only supports sigs up to about 252 bytes. See code to fix BER encoding for this before you
* add a SigType with bigger signatures.
*
* @throws IllegalArgumentException if too big
* @since 0.8.7, moved to SigUtil in 0.9.9
*/
private static byte[] sigBytesToASN1(byte[] sig) {
//System.out.println("pre TO asn1\n" + net.i2p.util.HexDump.dump(sig));
int len = sig.length;
int sublen = len / 2;
byte[] tmp = new byte[sublen];
System.arraycopy(sig, 0, tmp, 0, sublen);
BigInteger r = new BigInteger(1, tmp);
byte[] rb = r.toByteArray();
if (rb.length > 127)
throw new IllegalArgumentException("FIXME R length > 127");
System.arraycopy(sig, sublen, tmp, 0, sublen);
BigInteger s = new BigInteger(1, tmp);
byte[] sb = s.toByteArray();
if (sb.length > 127)
throw new IllegalArgumentException("FIXME S length > 127");
int seqlen = rb.length + sb.length + 4;
if (seqlen > 255)
throw new IllegalArgumentException("FIXME seq length > 255");
int totlen = seqlen + 2;
if (seqlen > 127)
totlen++;
byte[] rv = new byte[totlen];
int idx = 0;
rv[idx++] = 0x30;
if (seqlen > 127)
rv[idx++] =(byte) 0x81;
rv[idx++] = (byte) seqlen;
rv[idx++] = 0x02;
rv[idx++] = (byte) rb.length;
System.arraycopy(rb, 0, rv, idx, rb.length);
idx += rb.length;
rv[idx++] = 0x02;
rv[idx++] = (byte) sb.length;
System.arraycopy(sb, 0, rv, idx, sb.length);
//System.out.println("post TO asn1\n" + net.i2p.util.HexDump.dump(rv));
return rv;
}
/**
* See above.
* Only supports sigs up to about 252 bytes. See code to fix BER encoding for bigger than that.
*
* @return len bytes
* @since 0.8.7, moved to SigUtil in 0.9.9
*/
private static byte[] aSN1ToSigBytes(byte[] asn, int len)
throws SignatureException {
//System.out.println("pre from asn1 len=" + len + "\n" + net.i2p.util.HexDump.dump(asn));
if (asn[0] != 0x30)
throw new SignatureException("asn[0] = " + (asn[0] & 0xff));
// handles total len > 127
int idx = 2;
if ((asn[1] & 0x80) != 0)
idx += asn[1] & 0x7f;
if (asn[idx] != 0x02)
throw new SignatureException("asn[2] = " + (asn[idx] & 0xff));
byte[] rv = new byte[len];
int sublen = len / 2;
int rlen = asn[++idx];
if ((rlen & 0x80) != 0)
throw new SignatureException("FIXME R length > 127");
if ((asn[++idx] & 0x80) != 0)
throw new SignatureException("R is negative");
if (rlen > sublen + 1)
throw new SignatureException("R too big " + rlen);
if (rlen == sublen + 1)
System.arraycopy(asn, idx + 1, rv, 0, sublen);
else
System.arraycopy(asn, idx, rv, sublen - rlen, rlen);
idx += rlen;
int slenloc = idx + 1;
if (asn[idx] != 0x02)
throw new SignatureException("asn[s] = " + (asn[idx] & 0xff));
int slen = asn[slenloc];
if ((slen & 0x80) != 0)
throw new SignatureException("FIXME S length > 127");
if ((asn[slenloc + 1] & 0x80) != 0)
throw new SignatureException("S is negative");
if (slen > sublen + 1)
throw new SignatureException("S too big " + slen);
if (slen == sublen + 1)
System.arraycopy(asn, slenloc + 2, rv, sublen, sublen);
else
System.arraycopy(asn, slenloc + 1, rv, len - slen, slen);
//System.out.println("post from asn1\n" + net.i2p.util.HexDump.dump(rv));
return rv;
}
public static void clearCaches() {
synchronized(_pubkeyCache) {
_pubkeyCache.clear();
}
synchronized(_privkeyCache) {
_privkeyCache.clear();
}
}
}

View File

@ -21,6 +21,7 @@ import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey; import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey; import net.i2p.data.SigningPublicKey;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
import net.i2p.util.ZipFileComment; import net.i2p.util.ZipFileComment;
@ -315,20 +316,29 @@ riCe6OlAEiNpcc6mMyIYYWFICbrDFTrDR3wXqwc/Jkcx6L5VVWoagpSzbo3yGhc=
/** @return success */ /** @return success */
private static final boolean genKeysCLI(String publicKeyFile, String privateKeyFile) { private static final boolean genKeysCLI(String publicKeyFile, String privateKeyFile) {
File pubFile = new File(publicKeyFile);
File privFile = new File(privateKeyFile);
if (pubFile.exists()) {
System.out.println("Error: Not overwriting file " + publicKeyFile);
return false;
}
if (privFile.exists()) {
System.out.println("Error: Not overwriting file " + privateKeyFile);
return false;
}
FileOutputStream fileOutputStream = null; FileOutputStream fileOutputStream = null;
I2PAppContext context = I2PAppContext.getGlobalContext(); I2PAppContext context = I2PAppContext.getGlobalContext();
try { try {
Object signingKeypair[] = context.keyGenerator().generateSigningKeypair(); Object signingKeypair[] = context.keyGenerator().generateSigningKeypair();
SigningPublicKey signingPublicKey = (SigningPublicKey) signingKeypair[0]; SigningPublicKey signingPublicKey = (SigningPublicKey) signingKeypair[0];
SigningPrivateKey signingPrivateKey = (SigningPrivateKey) signingKeypair[1]; SigningPrivateKey signingPrivateKey = (SigningPrivateKey) signingKeypair[1];
fileOutputStream = new FileOutputStream(publicKeyFile); fileOutputStream = new SecureFileOutputStream(pubFile);
signingPublicKey.writeBytes(fileOutputStream); signingPublicKey.writeBytes(fileOutputStream);
fileOutputStream.close(); fileOutputStream.close();
fileOutputStream = null; fileOutputStream = null;
fileOutputStream = new FileOutputStream(privateKeyFile); fileOutputStream = new SecureFileOutputStream(privFile);
signingPrivateKey.writeBytes(fileOutputStream); signingPrivateKey.writeBytes(fileOutputStream);
System.out.println("\r\nPrivate key written to: " + privateKeyFile); System.out.println("\r\nPrivate key written to: " + privateKeyFile);

View File

@ -6,14 +6,22 @@ package net.i2p.update;
* @since 0.9.4 * @since 0.9.4
*/ */
public enum UpdateType { public enum UpdateType {
TYPE_DUMMY, // Internal use only /** Dummy: internal use only */
TYPE_DUMMY,
NEWS, NEWS,
ROUTER_SIGNED, ROUTER_SIGNED,
ROUTER_UNSIGNED, ROUTER_UNSIGNED,
PLUGIN, PLUGIN,
/** unused */
GEOIP, GEOIP,
/** unused */
BLOCKLIST, BLOCKLIST,
/** unused */
RESEED, RESEED,
/** unused */
HOMEPAGE, HOMEPAGE,
ADDRESSBOOK /** unused */
ADDRESSBOOK,
/** @since 0.9.9 */
ROUTER_SIGNED_SU3
} }

View File

@ -1055,12 +1055,14 @@ public class EepGet {
URL url = new URL(_actualURL); URL url = new URL(_actualURL);
if ("http".equals(url.getProtocol())) { if ("http".equals(url.getProtocol())) {
String host = url.getHost(); String host = url.getHost();
if (host.toLowerCase(Locale.US).endsWith(".i2p"))
throw new MalformedURLException("I2P addresses must be proxied");
int port = url.getPort(); int port = url.getPort();
if (port == -1) if (port == -1)
port = 80; port = 80;
_proxy = new Socket(host, port); _proxy = new Socket(host, port);
} else { } else {
throw new IOException("URL is not supported:" + _actualURL); throw new MalformedURLException("URL is not supported:" + _actualURL);
} }
// an MUE is an IOE // an MUE is an IOE
//} catch (MalformedURLException mue) { //} catch (MalformedURLException mue) {
@ -1089,6 +1091,8 @@ public class EepGet {
post = true; post = true;
URL url = new URL(_actualURL); URL url = new URL(_actualURL);
String host = url.getHost(); String host = url.getHost();
if (host == null || host.length() <= 0)
throw new MalformedURLException("Bad URL, no host");
int port = url.getPort(); int port = url.getPort();
String path = url.getPath(); String path = url.getPath();
String query = url.getQuery(); String query = url.getQuery();

View File

@ -112,7 +112,8 @@ public class NativeBigInteger extends BigInteger {
* don't spew log messages. main() below overrides to true. * don't spew log messages. main() below overrides to true.
*/ */
private static boolean _doLog = System.getProperty("jbigi.dontLog") == null && private static boolean _doLog = System.getProperty("jbigi.dontLog") == null &&
I2PAppContext.getGlobalContext().isRouterContext(); I2PAppContext.getCurrentContext() != null &&
I2PAppContext.getCurrentContext().isRouterContext();
/** /**
* The following libraries are be available in jbigi.jar in all I2P versions * The following libraries are be available in jbigi.jar in all I2P versions

View File

@ -3,6 +3,7 @@ package net.i2p.util;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
@ -11,6 +12,9 @@ import net.i2p.I2PAppContext;
* Fetch exactly the first 'size' bytes into a stream * Fetch exactly the first 'size' bytes into a stream
* Anything less or more will throw an IOException * Anything less or more will throw an IOException
* No retries, no min and max size options, no timeout option * No retries, no min and max size options, no timeout option
* If the server does not return a Content-Length header of the correct size,
* the fetch will fail.
*
* Useful for checking .sud versions * Useful for checking .sud versions
* *
* @since 0.7.12 * @since 0.7.12
@ -19,12 +23,20 @@ import net.i2p.I2PAppContext;
public class PartialEepGet extends EepGet { public class PartialEepGet extends EepGet {
long _fetchSize; long _fetchSize;
/** @param size fetch exactly this many bytes */ /**
* Instantiate an EepGet that will fetch exactly size bytes when fetch() is called.
*
* @param proxyHost use null or "" for no proxy
* @param proxyPort use 0 for no proxy
* @param size fetch exactly this many bytes
*/
public PartialEepGet(I2PAppContext ctx, String proxyHost, int proxyPort, public PartialEepGet(I2PAppContext ctx, String proxyHost, int proxyPort,
OutputStream outputStream, String url, long size) { OutputStream outputStream, String url, long size) {
// we're using this constructor: // we're using this constructor:
// public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) { // public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries,
super(ctx, true, proxyHost, proxyPort, 0, size, size, null, outputStream, url, true, null, null); // long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) {
super(ctx, proxyHost != null && proxyPort > 0, proxyHost, proxyPort, 0,
size, size, null, outputStream, url, true, null, null);
_fetchSize = size; _fetchSize = size;
} }
@ -88,7 +100,8 @@ public class PartialEepGet extends EepGet {
} }
private static void usage() { private static void usage() {
System.err.println("PartialEepGet [-p 127.0.0.1:4444] [-l #bytes] url"); System.err.println("PartialEepGet [-p 127.0.0.1:4444] [-l #bytes] url\n" +
" (use -p :0 for no proxy)");
} }
@Override @Override
@ -96,6 +109,8 @@ public class PartialEepGet extends EepGet {
StringBuilder buf = new StringBuilder(2048); StringBuilder buf = new StringBuilder(2048);
URL url = new URL(_actualURL); URL url = new URL(_actualURL);
String host = url.getHost(); String host = url.getHost();
if (host == null || host.length() <= 0)
throw new MalformedURLException("Bad URL, no host");
int port = url.getPort(); int port = url.getPort();
String path = url.getPath(); String path = url.getPath();
String query = url.getQuery(); String query = url.getQuery();

View File

@ -46,18 +46,14 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.PipedInputStream; import java.io.PipedInputStream;
import java.io.PipedOutputStream; import java.io.PipedOutputStream;
import java.io.PrintWriter; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Locale; import java.util.Locale;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLHandshakeException;
@ -67,7 +63,8 @@ import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.Base64; import net.i2p.crypto.CertUtil;
import net.i2p.crypto.KeyStoreUtil;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
/** /**
@ -76,7 +73,7 @@ import net.i2p.data.DataHelper;
* Fails on bad certs (must have a valid cert chain) * Fails on bad certs (must have a valid cert chain)
* Self-signed certs or CAs not in the JVM key store must be loaded to be trusted. * Self-signed certs or CAs not in the JVM key store must be loaded to be trusted.
* *
* Since 0.8.2, loads additional trusted CA certs from $I2P/certificates/ and ~/.i2p/certificates/ * Since 0.8.2, loads additional trusted CA certs from $I2P/certificates/ssl/ and ~/.i2p/certificates/ssl/
* *
* @author zzz * @author zzz
* @since 0.7.10 * @since 0.7.10
@ -91,7 +88,7 @@ public class SSLEepGet extends EepGet {
/** may be null if init failed */ /** may be null if init failed */
private SavingTrustManager _stm; private SavingTrustManager _stm;
private static final boolean _isAndroid = SystemVersion.isAndroid(); private static final String CERT_DIR = "certificates/ssl";
/** /**
* A new SSLEepGet with a new SSLState * A new SSLEepGet with a new SSLState
@ -107,9 +104,39 @@ public class SSLEepGet extends EepGet {
* @since 0.8.2 * @since 0.8.2
*/ */
public SSLEepGet(I2PAppContext ctx, OutputStream outputStream, String url, SSLState state) { public SSLEepGet(I2PAppContext ctx, OutputStream outputStream, String url, SSLState state) {
this(ctx, null, outputStream, url, null);
}
/**
* A new SSLEepGet with a new SSLState
* @since 0.9.9
*/
public SSLEepGet(I2PAppContext ctx, String outputFile, String url) {
this(ctx, outputFile, url, null);
}
/**
* @param state an SSLState retrieved from a previous SSLEepGet with getSSLState(), or null.
* This makes repeated fetches from the same host MUCH faster,
* and prevents repeated key store loads even for different hosts.
* @since 0.9.9
*/
public SSLEepGet(I2PAppContext ctx, String outputFile, String url, SSLState state) {
this(ctx, outputFile, null, url, null);
}
/**
* outputFile, outputStream: One null, one non-null
*
* @param state an SSLState retrieved from a previous SSLEepGet with getSSLState(), or null.
* This makes repeated fetches from the same host MUCH faster,
* and prevents repeated key store loads even for different hosts.
* @since 0.9.9
*/
private SSLEepGet(I2PAppContext ctx, String outputFile, OutputStream outputStream, String url, SSLState state) {
// we're using this constructor: // we're using this constructor:
// public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) { // public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) {
super(ctx, false, null, -1, 0, -1, -1, null, outputStream, url, true, null, null); super(ctx, false, null, -1, 0, -1, -1, outputFile, outputStream, url, true, null, null);
if (state != null && state.context != null) if (state != null && state.context != null)
_sslContext = state.context; _sslContext = state.context;
else else
@ -177,70 +204,39 @@ public class SSLEepGet extends EepGet {
* else from $JAVA_HOME/lib/security/jssacacerts, * else from $JAVA_HOME/lib/security/jssacacerts,
* else from $JAVA_HOME/lib/security/cacerts. * else from $JAVA_HOME/lib/security/cacerts.
* *
* Then adds certs found in the $I2P/certificates/ directory * Then adds certs found in the $I2P/certificates/ssl/ directory
* and in the ~/.i2p/certificates/ directory. * and in the ~/.i2p/certificates/ssl/ directory.
* *
* @return null on failure * @return null on failure
* @since 0.8.2 * @since 0.8.2
*/ */
private SSLContext initSSLContext() { private SSLContext initSSLContext() {
KeyStore ks; KeyStore ks = KeyStoreUtil.loadSystemKeyStore();
try { if (ks == null) {
ks = KeyStore.getInstance(KeyStore.getDefaultType()); _log.error("Key Store init error");
} catch (GeneralSecurityException gse) {
_log.error("Key Store init error", gse);
return null; return null;
} }
boolean success = false; if (_log.shouldLog(Log.INFO)) {
String override = System.getProperty("javax.net.ssl.keyStore"); int count = KeyStoreUtil.countCerts(ks);
if (override != null)
success = loadCerts(new File(override), ks);
if (!success) {
if (_isAndroid) {
// thru API 13. As of API 14 (ICS), the file is gone, but
// ks.load(null, pw) will bring in the default certs?
success = loadCerts(new File(System.getProperty("java.home"), "etc/security/cacerts.bks"), ks);
} else {
success = loadCerts(new File(System.getProperty("java.home"), "lib/security/jssecacerts"), ks);
if (!success)
success = loadCerts(new File(System.getProperty("java.home"), "lib/security/cacerts"), ks);
}
}
if (!success) {
try {
// must be initted
ks.load(null, "changeit".toCharArray());
} catch (Exception e) {}
_log.error("All key store loads failed, will only load local certificates");
} else if (_log.shouldLog(Log.INFO)) {
int count = 0;
try {
for(Enumeration<String> e = ks.aliases(); e.hasMoreElements();) {
String alias = e.nextElement();
if (ks.isCertificateEntry(alias))
count++;
}
} catch (Exception foo) {}
_log.info("Loaded " + count + " default trusted certificates"); _log.info("Loaded " + count + " default trusted certificates");
} }
File dir = new File(_context.getBaseDir(), "certificates"); File dir = new File(_context.getBaseDir(), CERT_DIR);
int adds = addCerts(dir, ks); int adds = KeyStoreUtil.addCerts(dir, ks);
int totalAdds = adds; int totalAdds = adds;
if (adds > 0 && _log.shouldLog(Log.INFO)) if (adds > 0 && _log.shouldLog(Log.INFO))
_log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath()); _log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath());
if (!_context.getBaseDir().getAbsolutePath().equals(_context.getConfigDir().getAbsolutePath())) { if (!_context.getBaseDir().getAbsolutePath().equals(_context.getConfigDir().getAbsolutePath())) {
dir = new File(_context.getConfigDir(), "certificates"); dir = new File(_context.getConfigDir(), CERT_DIR);
adds = addCerts(dir, ks); adds = KeyStoreUtil.addCerts(dir, ks);
totalAdds += adds; totalAdds += adds;
if (adds > 0 && _log.shouldLog(Log.INFO)) if (adds > 0 && _log.shouldLog(Log.INFO))
_log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath()); _log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath());
} }
dir = new File(System.getProperty("user.dir")); dir = new File(System.getProperty("user.dir"));
if (!_context.getBaseDir().getAbsolutePath().equals(dir.getAbsolutePath())) { if (!_context.getBaseDir().getAbsolutePath().equals(dir.getAbsolutePath())) {
dir = new File(_context.getConfigDir(), "certificates"); dir = new File(_context.getConfigDir(), CERT_DIR);
adds = addCerts(dir, ks); adds = KeyStoreUtil.addCerts(dir, ks);
totalAdds += adds; totalAdds += adds;
if (adds > 0 && _log.shouldLog(Log.INFO)) if (adds > 0 && _log.shouldLog(Log.INFO))
_log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath()); _log.info("Loaded " + adds + " trusted certificates from " + dir.getAbsolutePath());
@ -261,118 +257,6 @@ public class SSLEepGet extends EepGet {
} }
return null; return null;
} }
/**
* Load all X509 Certs from a key store File into a KeyStore
* Note that each call reinitializes the KeyStore
*
* @return success
* @since 0.8.2
*/
private boolean loadCerts(File file, KeyStore ks) {
if (!file.exists())
return false;
InputStream fis = null;
try {
fis = new FileInputStream(file);
// "changeit" is the default password
ks.load(fis, "changeit".toCharArray());
} catch (GeneralSecurityException gse) {
_log.error("KeyStore load error, no default keys: " + file.getAbsolutePath(), gse);
try {
// not clear if null is allowed for password
ks.load(null, "changeit".toCharArray());
} catch (Exception foo) {}
return false;
} catch (IOException ioe) {
_log.error("KeyStore load error, no default keys: " + file.getAbsolutePath(), ioe);
try {
ks.load(null, "changeit".toCharArray());
} catch (Exception foo) {}
return false;
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
return true;
}
/**
* Load all X509 Certs from a directory and add them to the
* trusted set of certificates in the key store
*
* @return number successfully added
* @since 0.8.2
*/
private int addCerts(File dir, KeyStore ks) {
if (_log.shouldLog(Log.INFO))
_log.info("Looking for X509 Certificates in " + dir.getAbsolutePath());
int added = 0;
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (!f.isFile())
continue;
// use file name as alias
// https://www.sslshopper.com/ssl-converter.html
// No idea if all these formats can actually be read by CertificateFactory
String alias = f.getName().toLowerCase(Locale.US);
if (alias.endsWith(".crt") || alias.endsWith(".pem") || alias.endsWith(".key") ||
alias.endsWith(".der") || alias.endsWith(".key") || alias.endsWith(".p7b") ||
alias.endsWith(".p7c") || alias.endsWith(".pfx") || alias.endsWith(".p12"))
alias = alias.substring(0, alias.length() - 4);
boolean success = addCert(f, alias, ks);
if (success)
added++;
}
}
}
return added;
}
/**
* Load an X509 Cert from a file and add it to the
* trusted set of certificates in the key store
*
* @return success
* @since 0.8.2
*/
private boolean addCert(File file, String alias, KeyStore ks) {
InputStream fis = null;
try {
fis = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
if (_log.shouldLog(Log.INFO)) {
_log.info("Read X509 Certificate from " + file.getAbsolutePath() +
" Issuer: " + cert.getIssuerX500Principal() +
"; Valid From: " + cert.getNotBefore() +
" To: " + cert.getNotAfter());
}
try {
cert.checkValidity();
} catch (CertificateExpiredException cee) {
_log.error("Rejecting expired X509 Certificate: " + file.getAbsolutePath(), cee);
return false;
} catch (CertificateNotYetValidException cnyve) {
_log.error("Rejecting X509 Certificate not yet valid: " + file.getAbsolutePath(), cnyve);
return false;
}
ks.setCertificateEntry(alias, cert);
if (_log.shouldLog(Log.INFO))
_log.info("Now trusting X509 Certificate, Issuer: " + cert.getIssuerX500Principal());
} catch (GeneralSecurityException gse) {
_log.error("Error reading X509 Certificate: " + file.getAbsolutePath(), gse);
return false;
} catch (IOException ioe) {
_log.error("Error reading X509 Certificate: " + file.getAbsolutePath(), ioe);
return false;
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
return true;
}
/** /**
* From http://blogs.sun.com/andreas/resource/InstallCert.java * From http://blogs.sun.com/andreas/resource/InstallCert.java
@ -425,44 +309,12 @@ public class SSLEepGet extends EepGet {
} catch (Exception e) { } catch (Exception e) {
System.out.println(" WARNING: Certificate is not currently valid, it cannot be used"); System.out.println(" WARNING: Certificate is not currently valid, it cannot be used");
} }
saveCert(cert, new File(name)); CertUtil.saveCert(cert, new File(name));
} }
System.out.println("NOTE: To trust them, copy the certificate file(s) to the certificates directory and rerun without the -s option"); System.out.println("NOTE: To trust them, copy the certificate file(s) to the certificates directory and rerun without the -s option");
System.out.println("NOTE: EepGet failed, certificate error follows:"); System.out.println("NOTE: EepGet failed, certificate error follows:");
} }
private static final int LINE_LENGTH = 64;
/**
* Modified from:
* http://www.exampledepot.com/egs/java.security.cert/ExportCert.html
*
* This method writes a certificate to a file in base64 format.
* @since 0.8.2
*/
private static void saveCert(Certificate cert, File file) {
OutputStream os = null;
try {
// Get the encoded form which is suitable for exporting
byte[] buf = cert.getEncoded();
os = new FileOutputStream(file);
PrintWriter wr = new PrintWriter(os);
wr.println("-----BEGIN CERTIFICATE-----");
String b64 = Base64.encode(buf, true); // true = use standard alphabet
for (int i = 0; i < b64.length(); i += LINE_LENGTH) {
wr.println(b64.substring(i, Math.min(i + LINE_LENGTH, b64.length())));
}
wr.println("-----END CERTIFICATE-----");
wr.flush();
} catch (CertificateEncodingException cee) {
System.out.println("Error writing X509 Certificate " + file.getAbsolutePath() + ' ' + cee);
} catch (IOException ioe) {
System.out.println("Error writing X509 Certificate " + file.getAbsolutePath() + ' ' + ioe);
} finally {
try { if (os != null) os.close(); } catch (IOException foo) {}
}
}
/** /**
* An opaque class for the caller to pass to repeated instantiations of SSLEepGet. * An opaque class for the caller to pass to repeated instantiations of SSLEepGet.
* @since 0.8.2 * @since 0.8.2
@ -641,6 +493,8 @@ public class SSLEepGet extends EepGet {
int port = 0; int port = 0;
if ("https".equals(url.getProtocol())) { if ("https".equals(url.getProtocol())) {
host = url.getHost(); host = url.getHost();
if (host.toLowerCase(Locale.US).endsWith(".i2p"))
throw new MalformedURLException("I2P addresses unsupported");
port = url.getPort(); port = url.getPort();
if (port == -1) if (port == -1)
port = 443; port = 443;
@ -649,7 +503,7 @@ public class SSLEepGet extends EepGet {
else else
_proxy = SSLSocketFactory.getDefault().createSocket(host, port); _proxy = SSLSocketFactory.getDefault().createSocket(host, port);
} else { } else {
throw new IOException("Only https supported: " + _actualURL); throw new MalformedURLException("Only https supported: " + _actualURL);
} }
// an MUE is an IOE // an MUE is an IOE
//} catch (MalformedURLException mue) { //} catch (MalformedURLException mue) {

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
i2p (0.9.8-1) UNRELEASED; urgency=low
* New upstream 0.9.8
-- Kill Your TV <killyourtv@i2pmail.org> Mon, 30 Sep 2013 00:00:00 +0000
i2p (0.9.7.1-1) unstable; urgency=low i2p (0.9.7.1-1) unstable; urgency=low
* New upstream version 0.9.7.1 * New upstream version 0.9.7.1

View File

@ -71,10 +71,13 @@ Debian wrapper.config to try to prevent confusion.
# Priority at which to run the wrapper. See "man nice" for valid priorities. # Priority at which to run the wrapper. See "man nice" for valid priorities.
# nice is only used if a priority is specified. # nice is only used if a priority is specified.
@@ -175,48 +166,6 @@ @@ -172,64 +163,6 @@
# Workaround for Gentoo exit 1
JAVABINARY=$(awk -F'=' '/^ *wrapper\.java\.command/{print $2}' "$WRAPPER_CONF") fi
-# Workaround for Gentoo
-JAVABINARY=$(awk -F'=' '/^ *wrapper\.java\.command/{print $2}' "$WRAPPER_CONF")
-
-if [ -e /etc/gentoo-release ]; then -if [ -e /etc/gentoo-release ]; then
- if [ $JAVABINARY = java ]; then - if [ $JAVABINARY = java ]; then
- if [ -x /etc/java-config-2/current-system-vm/bin/java ]; then - if [ -x /etc/java-config-2/current-system-vm/bin/java ]; then
@ -103,44 +106,54 @@ Debian wrapper.config to try to prevent confusion.
- echo "**`gettext 'Failed to load the wrapper'`**" - echo "**`gettext 'Failed to load the wrapper'`**"
- case `uname -s` in - case `uname -s` in
- FreeBSD) - FreeBSD)
- echo - # We should never get here on recent versions of FreeBSD
- echo "The wrapper requires libiconv to be on your system." - if ! $(pkg_info -E 'libiconv*' > /dev/null 2>&1); then
- echo "It can be installed with pkg_add -r libiconv" - echo
- echo - echo "The wrapper requires libiconv."
- exit 1 - echo
- echo "It can be installed with pkg_add -r libiconv"
- echo
- fi
- ;; - ;;
- *) - *)
- echo - echo
- unsupported - unsupported
- exit 1
- ;; - ;;
- esac - esac
- exit 1
-} -}
-
-if $(which ldd > /dev/null 2>&1); then
- # This should cover every *NIX other than OSX since OSX doesn't have ldd.
- # OSX has otool. Is otool on every OSX installation? Is otool's output the same as ldd's?
- # The wrapper we ship for OSX are for PPC and Intel, so maybe we don't need to worry about OSX?
- if (ldd "$WRAPPER_CMD" |grep -q 'not found') > /dev/null 2>&1 || \
- ! (ldd "$WRAPPER_CMD" > /dev/null 2>&1); then
- failed
- fi
-fi
- -
if [ -n "$FIXED_COMMAND" ] if [ -n "$FIXED_COMMAND" ]
then then
COMMAND="$FIXED_COMMAND" COMMAND="$FIXED_COMMAND"
@@ -928,9 +877,6 @@ @@ -940,7 +873,7 @@
# The string passed to eval must handles spaces in paths correctly. # The string passed to eval must handles spaces in paths correctly.
COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.java.command=\"$JAVABINARY\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" $ANCHORPROP $STATUSPROP $COMMANDPROP $LOCKPROP $LOGPROP wrapper.script.version=3.5.20 $ADDITIONAL_PARA" COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.java.command=\"$JAVABINARY\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" $ANCHORPROP $STATUSPROP $COMMANDPROP $LOCKPROP $LOGPROP wrapper.script.version=3.5.20 $ADDITIONAL_PARA"
eval $COMMAND_LINE - eval $COMMAND_LINE || failed
- if [ "$?" -ne "0" ]; then + eval $COMMAND_LINE
- failed
- fi
else else
eval echo `gettext '$APP_LONG_NAME is already running.'` eval echo `gettext '$APP_LONG_NAME is already running.'`
exit 1 exit 1
@@ -1054,9 +1000,6 @@ @@ -997,7 +930,6 @@
# The string passed to eval must handles spaces in paths correctly. if [ "X$pid" = "X" ]
COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.java.command=\"$JAVABINARY\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $STATUSPROP $COMMANDPROP $LOCKPROP $LOGPROP wrapper.script.version=3.5.20 $ADDITIONAL_PARA" then
eval $COMMAND_LINE eval echo " `gettext 'WARNING: $APP_LONG_NAME may have failed to start.'`"
- if [ "$?" -ne "0" ]; then - failed
- failed else
- fi eval echo ' running: PID:$pid'
else fi
eval echo `gettext '$APP_LONG_NAME is already running.'` @@ -1800,7 +1732,7 @@
exit 1
@@ -1793,7 +1736,7 @@
} }
showsetusermesg() { showsetusermesg() {
@ -149,7 +162,7 @@ Debian wrapper.config to try to prevent confusion.
} }
checkifstartingasroot() { checkifstartingasroot() {
@@ -1801,7 +1744,7 @@ @@ -1808,7 +1740,7 @@
echo "`gettext 'Running I2P as the root user is *not* recommended.'`" echo "`gettext 'Running I2P as the root user is *not* recommended.'`"
showsetusermesg showsetusermesg
echo echo
@ -158,7 +171,7 @@ Debian wrapper.config to try to prevent confusion.
exit 1 exit 1
fi fi
} }
@@ -1866,24 +1809,10 @@ @@ -1873,24 +1805,10 @@
status status
;; ;;
@ -327,66 +340,44 @@ Debian wrapper.config to try to prevent confusion.
- -
--- a/installer/resources/locale/po/messages_de.po --- a/installer/resources/locale/po/messages_de.po
+++ b/installer/resources/locale/po/messages_de.po +++ b/installer/resources/locale/po/messages_de.po
@@ -192,14 +192,14 @@ @@ -192,15 +192,15 @@
msgstr "Falls gestartet, fordere einen Java Thread dump an" msgstr "Falls gestartet, fordere einen Java Thread dump an"
#: ../i2prouter:1788 #: ../i2prouter:1803
-msgid "Please edit i2prouter and set the variable RUN_AS_USER" -msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgstr "Bitte bearbeite i2prouter und setze die Variable RUN_AS_USER" -msgstr "Bitte bearbeite i2prouter und setze die Variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER" +msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
+msgstr "Bitte bearbeite /etc/default/i2p und setze die Variable RUN_AS_USER" +msgstr "Bitte bearbeite /etc/default/i2p und setze die Variable RUN_AS_USER"
#: ../i2prouter:1793 #: ../i2prouter:1808
msgid "Running I2P as the root user is *not* recommended." msgid "Running I2P as the root user is *not* recommended."
msgstr "I2P als root Benutzer auszuführen ist *nicht* empfehlenswert." msgstr "I2P als root Benutzer auszuführen ist *nicht* empfehlenswert."
#: ../i2prouter:1796 #: ../i2prouter:1811
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true." -msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true." +msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr "" msgstr ""
-"Um I2P trotzdem als root auszuführen bearbeite i2prouter und setze ALLOW_ROOT=true." -"Um I2P trotzdem als root auszuführen bearbeite i2prouter und setze "
+"Um I2P trotzdem als root auszuführen bearbeite /etc/default/i2p und setze ALLOW_ROOT=true." +"Um I2P trotzdem als root auszuführen bearbeite /etc/default/i2p und setze "
"ALLOW_ROOT=true."
--- a/installer/resources/locale/po/messages_en.po --- a/installer/resources/locale/po/messages_en.po
+++ b/installer/resources/locale/po/messages_en.po +++ b/installer/resources/locale/po/messages_en.po
@@ -185,7 +185,7 @@ @@ -185,7 +185,7 @@
msgstr "" msgstr ""
#: ../i2prouter:1796 #: ../i2prouter:1803
-msgid "Please edit i2prouter and set the variable RUN_AS_USER" -msgid "Please edit i2prouter and set the variable RUN_AS_USER"
+msgid "Please edit /etc/defalt/i2p and set the variable RUN_AS_USER" +msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
msgstr "" msgstr ""
#: ../i2prouter:1801 #: ../i2prouter:1808
@@ -193,5 +193,5 @@ @@ -193,5 +193,5 @@
msgstr "" msgstr ""
#: ../i2prouter:1804 #: ../i2prouter:1811
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true." -msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true." +msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr "" msgstr ""
--- a/installer/resources/locale/po/messages_fr.po
+++ b/installer/resources/locale/po/messages_fr.po
@@ -189,8 +189,8 @@
msgstr "Request a Java thread dump if running."
#: ../i2prouter:1796
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgstr "Veuillez éditer $0 et paramétrer la variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
+msgstr "Veuillez éditer /etc/default/i2p et paramétrer la variable RUN_AS_USER"
#: ../i2prouter:1801
msgid "Running I2P as the root user is *not* recommended."
@@ -198,7 +198,7 @@
"Faire fonctionner I2P en tant qu'utilisateur root n'est *pas* recommandé."
#: ../i2prouter:1804
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
-"Pour exécuter en tant que root de toute façon, éditer $0 et mettre "
+"Pour exécuter en tant que root de toute façon, éditer /etc/default/i2p et mettre "
"ALLOW_ROOT=true."
--- a/installer/resources/locale/po/messages_it.po --- a/installer/resources/locale/po/messages_it.po
+++ b/installer/resources/locale/po/messages_it.po +++ b/installer/resources/locale/po/messages_it.po
@@ -187,7 +187,7 @@ @@ -187,7 +187,7 @@
@ -405,49 +396,6 @@ Debian wrapper.config to try to prevent confusion.
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true." -msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true." +msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr "" msgstr ""
--- a/installer/resources/locale/po/messages_ru.po
+++ b/installer/resources/locale/po/messages_ru.po
@@ -190,16 +190,16 @@
msgstr "Запросить дамп нитей Java, если запущено."
#: ../i2prouter:1796
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
msgstr ""
-"Пожалуйста отредактируйте i2prouter и установите переменную RUN_AS_USER"
+"Пожалуйста отредактируйте /etc/default/i2p и установите переменную RUN_AS_USER"
#: ../i2prouter:1801
msgid "Running I2P as the root user is *not* recommended."
msgstr "Запуск I2P от имени root НЕ рекомендовано."
#: ../i2prouter:1804
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
-"Чтобы всё равно запустить из-под root, отредактируйте i2prouter и установите "
+"Чтобы всё равно запустить из-под root, отредактируйте /etc/default/i2p и установите "
"ALLOW_ROOT=true."
--- a/installer/resources/locale/po/messages_sv.po
+++ b/installer/resources/locale/po/messages_sv.po
@@ -187,13 +187,13 @@
msgstr "Fråga efter en Java thread dump vid drift."
#: ../i2prouter:1780
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgstr "Var god ändra i2prouter och sätt variabeln RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
+msgstr "Var god ändra /etc/default/i2p och sätt variabeln RUN_AS_USER"
#: ../i2prouter:1785
msgid "Running I2P as the root user is *not* recommended."
msgstr "Att köra I2P som användare root är *inte* rekommenderat."
#: ../i2prouter:1788
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
-msgstr "För att köra som root iallafall, ändra i2prouter och sätt ALLOW_ROOT=true"
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
+msgstr "För att köra som root iallafall, ändra /etc/default/i2p och sätt ALLOW_ROOT=true"
--- a/installer/resources/locale/po/messages_zh.po --- a/installer/resources/locale/po/messages_zh.po
+++ b/installer/resources/locale/po/messages_zh.po +++ b/installer/resources/locale/po/messages_zh.po
@@ -187,13 +187,13 @@ @@ -187,13 +187,13 @@
@ -530,3 +478,67 @@ Debian wrapper.config to try to prevent confusion.
-"Para executar como root mesmo assim, editar o i2prouter e configurar a " -"Para executar como root mesmo assim, editar o i2prouter e configurar a "
+"Para executar como root mesmo assim, editar o /etc/default/i2p e configurar a " +"Para executar como root mesmo assim, editar o /etc/default/i2p e configurar a "
"variável ALLOW_ROOT=true." "variável ALLOW_ROOT=true."
--- a/installer/resources/locale/po/messages_fr.po
+++ b/installer/resources/locale/po/messages_fr.po
@@ -187,13 +187,13 @@
msgstr "Request a Java thread dump if running."
#: ../i2prouter:1796
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgstr "Veuillez éditer i2prouter et paramétrer la variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
+msgstr "Veuillez éditer /etc/default/i2p et paramétrer la variable RUN_AS_USER"
#: ../i2prouter:1801
msgid "Running I2P as the root user is *not* recommended."
msgstr "Faire fonctionner I2P en tant qu'utilisateur root n'est *pas* recommandé."
#: ../i2prouter:1804
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
-msgstr "Pour exécuter en tant que root de toute façon, éditer i2prouter et mettre ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
+msgstr "Pour exécuter en tant que root de toute façon, éditer /etc/default/i2p et mettre ALLOW_ROOT=true."
--- a/installer/resources/locale/po/messages_ru.po
+++ b/installer/resources/locale/po/messages_ru.po
@@ -190,16 +190,16 @@
msgstr "Запросить дамп нитей Java, если запущено."
#: ../i2prouter:1803
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
msgstr ""
-"Пожалуйста отредактируйте i2prouter и установите переменную RUN_AS_USER"
+"Пожалуйста отредактируйте /etc/default/i2p и установите переменную RUN_AS_USER"
#: ../i2prouter:1808
msgid "Running I2P as the root user is *not* recommended."
msgstr "Запуск I2P от имени root НЕ рекомендовано."
#: ../i2prouter:1811
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
-"Чтобы всё равно запустить из-под root, отредактируйте i2prouter и установите "
+"Чтобы всё равно запустить из-под root, отредактируйте /etc/default/i2p и установите "
"ALLOW_ROOT=true."
--- a/installer/resources/locale/po/messages_sv.po
+++ b/installer/resources/locale/po/messages_sv.po
@@ -187,14 +187,14 @@
msgstr "Fråga efter en Java thread dump vid drift."
#: ../i2prouter:1803
-msgid "Please edit i2prouter and set the variable RUN_AS_USER"
-msgstr "Var god ändra i2prouter och set variabeln RUN_AS_USER"
+msgid "Please edit /etc/default/i2p and set the variable RUN_AS_USER"
+msgstr "Var god ändra /etc/default/i2p och set variabeln RUN_AS_USER"
#: ../i2prouter:1808
msgid "Running I2P as the root user is *not* recommended."
msgstr "Att köra I2P som användare root är *inte* rekommenderat."
#: ../i2prouter:1811
-msgid "To run as root anyway, edit i2prouter and set ALLOW_ROOT=true."
+msgid "To run as root anyway, edit /etc/default/i2p and set ALLOW_ROOT=true."
msgstr ""
-"För att köra som root oavsett, ändra i2prouter och sätt ALLOW_ROOT=true"
+"För att köra som root oavsett, ändra /etc/default/i2p och sätt ALLOW_ROOT=true"

View File

@ -15,8 +15,8 @@ a soname to shut lintian up.
UNIXTYPE="linux" UNIXTYPE="linux"
fi fi
COMPILEFLAGS="-fPIC -Wall $CFLAGS" COMPILEFLAGS="-fPIC -Wall $CFLAGS"
- INCLUDES="-I. -I../../jbigi/include -I$JAVA_HOME/include -I$JAVA_HOME/include/${UNIXTYPE}" - INCLUDES="-I. -I../../jbigi/include -I$JAVA_HOME/include -I$JAVA_HOME/include/${UNIXTYPE} -I/usr/local/include"
+ INCLUDES="-I. -I./jbigi/include -I$JAVA_HOME/include -I$JAVA_HOME/include/${UNIXTYPE}" + INCLUDES="-I. -I./jbigi/include -I$JAVA_HOME/include -I$JAVA_HOME/include/${UNIXTYPE} -I/usr/local/include"
LINKFLAGS="-shared -Wl,-soname,libjbigi.so" LINKFLAGS="-shared -Wl,-soname,libjbigi.so"
LIBFILE="libjbigi.so";; LIBFILE="libjbigi.so";;
*) *)
@ -26,6 +26,6 @@ a soname to shut lintian up.
rm -f jbigi.o $LIBFILE rm -f jbigi.o $LIBFILE
-$CC -c $COMPILEFLAGS $INCLUDES ../../jbigi/src/jbigi.c || exit 1 -$CC -c $COMPILEFLAGS $INCLUDES ../../jbigi/src/jbigi.c || exit 1
+$CC -c $COMPILEFLAGS $INCLUDES ./jbigi/src/jbigi.c || exit 1 +$CC -c $COMPILEFLAGS $INCLUDES ./jbigi/src/jbigi.c || exit 1
$CC $LINKFLAGS $INCLUDES -o $LIBFILE jbigi.o $INCLUDELIBS $STATICLIBS || exit 1 $CC $LINKFLAGS $INCLUDES -o $LIBFILE jbigi.o $INCLUDELIBS $STATICLIBS $LIBPATH || exit 1
exit 0 exit 0

37
debian/po/sv.po vendored
View File

@ -1,29 +1,30 @@
# Swedish debconf translation # SOME DESCRIPTIVE TITLE.
# Copyright (C) 2011 The I2P Project # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the i2p package. # This file is distributed under the same license as the PACKAGE package.
# #
# Translators: # Translators:
# Martin Svensson <digitalmannen@gmail.com>, 2011. # hottuna <i2p@robertfoss.se>, 2013
# Martin Svensson <digitalmannen@gmail.com>, 2011
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: I2P\n" "Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n" "Report-Msgid-Bugs-To: https://trac.i2p2.de/\n"
"POT-Creation-Date: 2011-12-27 22:25+0000\n" "POT-Creation-Date: 2011-12-27 22:25+0000\n"
"PO-Revision-Date: 2011-12-26 09:48+0000\n" "PO-Revision-Date: 2013-09-22 05:00+0000\n"
"Last-Translator: Martin Svensson <digitalmannen@gmail.com>\n" "Last-Translator: hottuna <i2p@robertfoss.se>\n"
"Language-Team: Swedish (Sweden) (http://www.transifex.net/projects/p/I2P/" "Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/"
"team/sv_SE/)\n" "language/sv_SE/)\n"
"Language: sv_SE\n" "Language: sv_SE\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. Type: boolean #. Type: boolean
#. Description #. Description
#: ../i2p.templates:2001 #: ../i2p.templates:2001
msgid "Should the I2P router be started at boot?" msgid "Should the I2P router be started at boot?"
msgstr "Skall I2P rutern startas vid uppstart?" msgstr "Ska I2P routern startas vid systemstart?"
#. Type: boolean #. Type: boolean
#. Description #. Description
@ -39,7 +40,7 @@ msgstr ""
#. Description #. Description
#: ../i2p.templates:3001 #: ../i2p.templates:3001
msgid "I2P daemon user:" msgid "I2P daemon user:"
msgstr "Konto för I2P tjänsten:" msgstr "Användare för I2P tjänsten:"
#. Type: string #. Type: string
#. Description #. Description
@ -50,10 +51,10 @@ msgid ""
"account name here. For example, if your previous I2P installation is at /" "account name here. For example, if your previous I2P installation is at /"
"home/user/i2p, you may enter 'user' here." "home/user/i2p, you may enter 'user' here."
msgstr "" msgstr ""
"Som standard är I2P inställt för att köras under kontot i2psvc mär den körs " "Som standard är I2P inställt för att köras under användaren i2psvc när det "
"som tjänst. För att använda ett **existerande** I2P profil, ange ett annat " "körs som tjänst. För att använda ett **existerande** I2P profil, ange en "
"konto här. Exempelvis, om din tidigare I2P installation är /home/user/i2p så " "annan användare här. Exempelvis, om din tidigare I2P installation är /home/"
"ange 'user' här." "user/i2p så ange 'user' här."
#. Type: string #. Type: string
#. Description #. Description
@ -63,19 +64,19 @@ msgid ""
"here, the chosen username *MUST* already exist." "here, the chosen username *MUST* already exist."
msgstr "" msgstr ""
"OBS! Viktigt: Om en annan användare än standard 'i2psvc' skrivs in här. " "OBS! Viktigt: Om en annan användare än standard 'i2psvc' skrivs in här. "
"\"MÅSTE\" det användarnamnet redan existera." "*MÅSTE* det användarnamnet redan existera."
#. Type: string #. Type: string
#. Description #. Description
#: ../i2p.templates:4001 #: ../i2p.templates:4001
msgid "Memory that can be allocated to I2P:" msgid "Memory that can be allocated to I2P:"
msgstr "Minne som kan tilldelas I2P" msgstr "Minne som kan tilldelas I2P:"
#. Type: string #. Type: string
#. Description #. Description
#: ../i2p.templates:4001 #: ../i2p.templates:4001
msgid "By default, I2P will only be allowed to use up to 128MB of RAM." msgid "By default, I2P will only be allowed to use up to 128MB of RAM."
msgstr "Som standard kommer I2P bara att använda 128MB RAM " msgstr "Som standard kommer I2P bara att använda up till 128MB RAM."
#. Type: string #. Type: string
#. Description #. Description

View File

@ -1,5 +1,115 @@
2013-10-06 zzz
Prop from branch i2p.i2p.zzz.ecdsa:
* Build:
- Generate su3 file in release target
- Add zzz's new RSA 4096 pubkey cert for updates
- Fix checkcerts.sh
* Console: Move advanced setting to HelperBase
* DSAEngine changes:
- Implement raw sign/verify for other SigTypes
- Add sign/verify methods using Java keys
* ECDSA Support:
- Add ECConstants which looks for named curves and falls back to
explicitly defining the curves
- Add support for ECDSA to SigType, DSAEngine and KeyGenerator
- Attempt to add BC as a Provider
- genSpec: fallback to BC provider
* EepGet:
- Fix non-proxied PartialEepGet
- Prevent non-proxied eepget for an I2P host
* KeyGenerator changes:
- Generate key pairs for all supported SigTypes
- KeyPairGen: Catch ProviderException, fallback to BC provider
- Add KeyGenerator main() tests
* KeyRing and DirKeyRing added: simple backend for storing X.509 certs
* KeyStoreUtil added:
- Consolidate KeyStore code from SSLEepGet, I2CPSSLSocketFactory,
SSLClientListenerRunner, and RouterConsoleRunner into new
KeyStoreUtil and CertUtil classes in net.i2p.crypto (ticket #744)
- Change default to RSA 2048 (ticket #1017)
- Set file modes on written keys
- Overwrite check in createKeys()
- New getCert(), getKey()
- Extend keygen max wait
- Read back private key to verify after keygen
- Validate cert after reading from file
- Validate CN in cert
- Specify cert signature algorithm when generating keys
* NativeBigInteger: Tweak to prevent early context instantiation
* RSA support added: constants, parameters, sig types, support in DSAEngine, KeyGenerator, SigUtil
* SHA1Hash: Add no-arg constructor
* SigType changes:
- Add parameters (curve specs) to SigTypes
- Add getHashInstance()
- Add RSA, fix ECDSA
- Renumber, rename, comment out types that are too short.
* SigUtil added:
- Converters from Java formats (ASN.1, X.509, PKCS#8)
to I2P formats for Signatures and SigningKeys
- Move ASN.1 converter from DSAEngine to SigUtil, generalize
for variable length, add support for longer sequences,
add more sanity checks, add more exceptions
- Move I2P-to-Java DSA key conversion from DSAEngine to SigUtil
- Add Java-to-I2P DSA key conversion
- Add Java key import
- New split() and combine() methods
* SSLEepGet: Move all certificates to certificates/ssl, in preparation
for other certificate uses by SU3File
* SU3File changes:
- Support all SigTypes
- Implement keygen
- Readahead to get sigtype on verify, as we need the hash type
- Enum for content type
- Add unknown content type, make default
- Fix NPE if private key not found or sign fails
- Store generated keys in keystore, and get private key from keystore
for signing, in Java format
- Use Java keys to sign and verify so we don't
lose the key parameters in the conversion to I2P keys
- Type checking of Java private key vs. type when signing
- Use certs instead of public keys for verification
- Fix arg processing
- Improve validate-without-extract
- New extract command
- Change static fields to avoid early context init
- Reduce PRNG buffer size for faster signing
* Update: Preliminary work for su3 router updates:
- New ROUTER_SIGNED_SU3 UpdateType
- Add support for torrent and HTTP
- Refactor UpdateRunners to return actual UpdateType
- Deal with signed/su3 conflicts
- Verify and extract su3 files.
- Stub out support for clearnet su3 updating
- New config for proxying news, separate from proxying update
- PartialEepGet and SSLEepGet tweaks to support clearnet update
- Remove proxy, key, and url config from /configupdate
- More URI checks in UpdateRunner
- Add https support for news fetch
- Add su3 mime type
- Reset found version in update loop so we don't fetch from
the next host too.
- Prevent NPE on version after SSL fetch
* 2013-10-02 0.9.8.1 released
2013-10-01 zzz
* Startup: Fix rekeying on Windows (tickets #1056, 1057)
* 2013-09-30 0.9.8 released
2013-09-26 kytv
* French, German, Russian, and Swedish translation updates from Transifex
* Update geoip.txt based on Maxmind GeoLite Country database from 2013-09-03
2013-09-23 zzz
* Console: Add /proof page which can copied to prove you run a router
2013-09-20 kytv
* Chinese, French, German, Russian, and Swedish translation updates from
Transifex
2013-09-17 zzz 2013-09-17 zzz
- Revert expl. default back to 2 hops, wait for next release * Revert expl. default back to 2 hops, wait for next release
2013-09-07 zzz 2013-09-07 zzz
* Crypto: Don't use "short exponent" on faster platforms. * Crypto: Don't use "short exponent" on faster platforms.

View File

@ -4,7 +4,7 @@
<info> <info>
<appname>i2p</appname> <appname>i2p</appname>
<appversion>0.9.7.1</appversion> <appversion>0.9.8.1</appversion>
<authors> <authors>
<author name="I2P" email="http://www.i2p2.de/"/> <author name="I2P" email="http://www.i2p2.de/"/>
</authors> </authors>

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