diff --git a/apps/desktopgui/LICENSE b/apps/desktopgui/LICENSE
new file mode 100644
index 000000000..61febe901
--- /dev/null
+++ b/apps/desktopgui/LICENSE
@@ -0,0 +1,15 @@
+Desktop GUI: provides a simple GUI for I2P.
+Copyright (C) 2009 Mathias De Maré
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; only version 2 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\ No newline at end of file
diff --git a/apps/desktopgui/build.xml b/apps/desktopgui/build.xml
new file mode 100644
index 000000000..c7ba1be11
--- /dev/null
+++ b/apps/desktopgui/build.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+ Builds, tests, and runs the project desktopgui.
+
+
+
diff --git a/apps/desktopgui/desktopgui/resources/howto/howto.html b/apps/desktopgui/desktopgui/resources/howto/howto.html
new file mode 100644
index 000000000..ea1b025c7
--- /dev/null
+++ b/apps/desktopgui/desktopgui/resources/howto/howto.html
@@ -0,0 +1,261 @@
+
+
+ Small Guide to I2P
+
+
+ Small Guide to I2P
+
+ So, what's this all about?
+
+ I2P builds up a new net inside the usual internet, connecting nodes together
+ via encrypted connections.
+ It is a JAVA prgram with its most used part (the encryption of the data) written
+ in handoptimized assembler code.
+ It will use your bandwith, your RAM and your CPU. It will use them all up if you
+ do not limit it.
+ I2P will route unknown traffic through your node, even stuff you dislike.
+ As that data is encrypted, nobody knows whats data went to or drom your node.
+
+
+
+ First, ALWAYS use the latest stable release.
+ Development releases are called "mtn version" and are marked with a -, e.g.
+ 0.6.5-1. Those are usually useable by all but could do harm to your I2P
+ experience.
+ You can get the latest MTN builds from my eepsite echelon.i2p, but always
+ remember: I built them, you need to trust me not to changed the code!
+ After you get the right "i2pupdate.zip" file, put that file into the I2P
+ directory and hit restart on the router console http://127.0.0.1:7657.
+ Do NOT deflate the zip file!
+
+
+
+ I2P is very dynamic - after startup it tries to get known to other I2P routers
+ and measures their speed - you need to wait some 10-120 minutes until your
+ I2P router knows enough other ones to obtain full power of I2P.
+
+
+ Filesharing
+
+
+ I2P is able to do anonymous filesharing.
+ But as there are NO gateways between real net and I2P, you can only share/
+ download torrents from within I2P. Look e.g. postman.i2p or planet.i2p.
+ You CANNOT use azureus, utorrent or any other usual client.
+ You cannot download anonymous torrents from mininova, piratebay or else.
+ You need to use I2P internal torrents and I2P aware programs like
+ I2Psnark (builtin, suitable for 1-20 torrents)
+ I2PRufus (external, python, high CPU load, suitable >20 torrents) http://echelon.i2p/i2prufus
+ I2P-BT (external, python)
+ I2PsnarkXL (mod of I2Psnark made by fwd)
+
+
+
+ There are also gnutella and edonkey clients:
+ i2phex for gnutella (http://echelon.i2p/i2phex)
+ imule for edonkey (http://echelon.i2p/imule)
+
+
+
+ Remember, as I2P uses other routers to route your traffic via 1-6 other PCs,
+ your transferrates in P2P are slower than in usual internet.
+ But you are anonymous, no one can easily (within 2 months-2 years) get your IP!
+ torrents inside of I2P reaches up to 50 kb/sec, usual are 10-20 kb/sec per torrent
+ i2phex reaches up to 20 kb/sec, usually 5-10 kb/sec
+ imule in times reaches 10 kb/sec, usually 5-10 kb/sec
+
+
+
+ In I2PHex and imule you can just tell "share file or directory", in torrent
+ you need to create a .torrent file and upload that (and ONLY that small .torrent)
+ file to the trackers like tracker.postman.i2p/
+
+
+
+ I2P is a smaller net (1000 users) which grows slowly. As of which amount of shared
+ data will slowly rise.
+
+
+
+ I2P is anonymous and it does not censor - there is no administrator.
+ There IS unwanted stuff like kiddyporn, nazism, or else.
+ If you dislike all this, do not use I2P.
+ There is NO way to prohibite this stuff to appear in a anonymous net like I2P.
+ (as that stuff is available shows the anonymity and transfer function of I2P
+ is working well enough)
+ You can delete the destinations in question from your local hosts.txt file (or
+ deface them) which will partly prevent you to reach those bad sies by accident.
+
+
+ Internet (the websites)
+
+
+ Only one outproxy (gateway I2P - webpages in usual Internet) is working.
+ It is NOT official from I2P, I2P does work without.
+ If that outproxy is slow, offline, gone,.. I2P still works on and cannot do
+ anything to change that failure.
+ That outproxy translates usual internet webpages into the I2P net and you can
+ reach them via your Router.
+ The best way for usual webpages is TOR, not that outproxy.
+ Remember: the owner of the outproxy got ALL traffic from all I2P users
+ visiting Internet pages and will risk that into the police!
+
+
+
+ This proxy is false.i2p. In newer I2P routers it is enabled, but not in
+ older ones. Go to http://127.0.0.1:7657/i2ptunnel/index.jsp tunnels page and
+ click on the eepProxy tunnel. Change the entry for the "Outproxies" to false.i2p
+ and save. On the tunnels page, stop the epproxy tunnel and start it again,
+ now your router will use the false.i2p outproxy.
+
+
+
+ No other (known) gateways are setup and running. No one we know will run
+ the gateway for torrent or any other P2P data (and risk his life).
+
+
+ Bandwidth
+
+ http://127.0.0.1:7657/config.jsp
+
+ Setup your bandwith wisely. Know your linespeed!
+
+
+ E.g. most common terms are:
+ 1Mbit = roughly 100 kbyte/sec
+ 10 MBit = roughly 1100 kbyte/sec
+ 512 kbit = roughly 50 kbyte/sec
+ or in germany:
+ 16000er = roughly 1500 kbyte/sec
+ 6000er = roughly 600 kbyte/sec
+ 1000er = roughly 100 kb/sec
+
+
+
+ Set your bandwith limits to 10% under your line speed and burst rate to
+ your line speed.
+ Set the bandwith share percentage to:
+ >80% if lowest bandwith setting is >50k
+ >50% if lowest bandwith setting is >30k
+ >20% if lowest bandwith setting is >16k
+
+
+ There is no shared bandwith under 16k.
+
+
+ Limit your participating tunnels (shared bandwith) on:
+ http://127.0.0.1:7657/configadvanced.jsp
+ with the line:
+ router.maxParticipatingTunnels=500
+
+
+
+ 2000 is for roughly 600 kb/sec - very high value with high CPU load
+ 1000 is for roughly 300 kb/sec
+ 600 is a good value for 150-200kb/sec
+ 300 is roughly 90 kb/sec
+ 150 roughly 50 kb/sec
+ Remember: even failed tunnel requests will result in a part tunnel on the hops in between!
+ Those said, there are far more part tunnels unused than used in the live net under load, which
+ results in slower bandwith per tunnel in the end.
+ It is wise to first limit the bandwith and afterwards the part tunnels, e.g. set some more part
+ tunnels and let I2P reach the bandwith limit instead of the part tunnels limit!
+
+
+ What is shared bandwidth?
+
+
+ I2P transports your date from the client to the server through 1-6 hops
+ (other I2P routers). Each of this hops sees the data from you as "participating
+ tunnel" - which is the shared bandwith of them.
+ With this in mind, I2P needs some amount of this shared bandwith at some
+ amount of routers.
+ Share as much as you are able of - others will thank you!
+
+
+
+ With the "share percentage" set like above, you will obtain enough speed for
+ your own traffic and obtain some participating tunnels (if >16kb/sec) with some
+ noise traffic to hide your traffic in the stream.
+
+
+
+ With release 0.6.5 there is some method to prefer your own traffic ahead
+ of shared traffic which will result in better experience to you!
+
+
+ Addressbook
+
+
+ I2P uses a local addressbook to link short DNS names with the internal used 512bit
+ hashes (which are destination IDs).
+ Those links are saved insside the hosts.txt and userhosts.txt files in the i2p
+ directory.
+ Hosts which are not in those files cannot be reached via the short DNS names
+ and a error message with "jumper links" will appear. Those links will ask
+ some hosts services and forward to the correct site (if the site is known to them).
+ Those hosts services just made a form to add new "hosts" and those results public
+ available.
+ You can subscribe to those hosts service and let your hosts.txt file be updated
+ automatic. Go to http://127.0.0.1:7657/susidns/subscriptions.jsp SusiDNS
+ and enter the hosts services into the textbox (and save afterwards):
+ http://www.i2p2.i2p/hosts.txt
+ http://stats.i2p/cgi-bin/newhosts.txt
+ http://tino.i2p/hosts.txt
+ http://i2host.i2p/cgi-bin/i2hostag
+ You can add one of them, two or all.
+ SusiDNS will now ask those hosts for new entries to the hosts.txt and those
+ will be added to your hosts.txt. The userhosts.txt will ONLY be updated by
+ yourself (the user) and not be published into the net!
+ Remember, names once set could not be changed! If you loose your key (destination
+ ID) to your eepsite, service,..., there is no way to change the linking
+ between the DNS name and the (lost) destination ID automatic! Only manual by each
+ user itself - great topic to discuss of need to renew DNS hostnames.
+ As this subscription will not update old entries, you can "deface" unwanted
+ eepsites with a false key and if you hit the bad name in browser by accident,
+ you will not see the bad stuff!
+
+
+ Out of Memory errors
+
+
+ If your router hits the Out of Memory error - check your logs!
+ Usual point for OOM are to much torrents in i2psnark - i2psnark is a real
+ memory hogg and >10 torrents it requiers hell a lot of memory!
+
+
+
+ Maybe it is possible for you to increase the wrapper memory config.
+ This ONLY works if you start the I2P service restartable with console
+ (on Windows).
+ In I2P directory edit the wrapper.config file and change the values:
+ wrapper.java.maxmemory=256 (or even to 512, IF possible)
+ Afterwards shutdown I2P complete (the service) and restart it.
+
+
+ Blocklists
+
+
+ Sometimes attackers trying to flood the I2P net and try to do some harm.
+ And some folks setting localnet IPs as their internet reachable address.
+ To prevent those bad router to harm the local router, I2P implemented
+ a local blocklist system. It is NOT integrated automatic as it could
+ really harm your I2P experience if setup the wrong way.
+ The way to enable blocklists is:
+ Get the file http://zzz.i2p/files/blocklist.txt and copy this file into the
+ I2P directory.
+ On http://127.0.0.1:7657/configadvanced.jsp set the option
+ router.blocklist.enable=true - click on Apply and restart the router
+ with the restart link left on router console.
+ The blockfile.txt file follows a special order, you´ll get it if you read it.
+ The first entry is the reason to be shown on http://127.0.0.1:7657/profiles.jsp
+ at the bottom in the shitlist section.
+ The second entry is the IP or the dest ID of a router.
+ Right now there are only private subnets in the blocklist AND one chinese router
+ which floods the floodfill DB while restarting every few minutes with a different
+ router ID and far to less bandwith for being a floodfill router.
+
+
+ (By echelon -- echelon.i2p )
+
+
diff --git a/apps/desktopgui/desktopgui/resources/logo/logo.jpg b/apps/desktopgui/desktopgui/resources/logo/logo.jpg
new file mode 100644
index 000000000..f1b5ccfc8
Binary files /dev/null and b/apps/desktopgui/desktopgui/resources/logo/logo.jpg differ
diff --git a/apps/desktopgui/lib/appframework.jar b/apps/desktopgui/lib/appframework.jar
new file mode 100644
index 000000000..0b8ff0145
Binary files /dev/null and b/apps/desktopgui/lib/appframework.jar differ
diff --git a/apps/desktopgui/lib/swing-worker.jar b/apps/desktopgui/lib/swing-worker.jar
new file mode 100644
index 000000000..bcdd9d910
Binary files /dev/null and b/apps/desktopgui/lib/swing-worker.jar differ
diff --git a/apps/desktopgui/manifest.mf b/apps/desktopgui/manifest.mf
new file mode 100644
index 000000000..328e8e5bc
--- /dev/null
+++ b/apps/desktopgui/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/apps/desktopgui/nbproject/build-impl.xml b/apps/desktopgui/nbproject/build-impl.xml
new file mode 100644
index 000000000..f8fea458d
--- /dev/null
+++ b/apps/desktopgui/nbproject/build-impl.xml
@@ -0,0 +1,629 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set src.dir
+ Must set test.src.dir
+ Must set build.dir
+ Must set dist.dir
+ Must set build.classes.dir
+ Must set dist.javadoc.dir
+ Must set build.test.classes.dir
+ Must set build.test.results.dir
+ Must set build.classes.excludes
+ Must set dist.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+
+
+
+
+
+ java -cp "${run.classpath.with.dist.jar}" ${main.class}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+ java -jar "${dist.jar.resolved}"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must set fix.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+ Must select one file in the IDE or set test.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/desktopgui/nbproject/genfiles.properties b/apps/desktopgui/nbproject/genfiles.properties
new file mode 100644
index 000000000..1b326007c
--- /dev/null
+++ b/apps/desktopgui/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=c4b345cd
+build.xml.script.CRC32=9785bb9a
+build.xml.stylesheet.CRC32=be360661
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=c4b345cd
+nbproject/build-impl.xml.script.CRC32=74d3fda2
+nbproject/build-impl.xml.stylesheet.CRC32=487672f9
diff --git a/apps/desktopgui/nbproject/project.properties b/apps/desktopgui/nbproject/project.properties
new file mode 100644
index 000000000..5e888e698
--- /dev/null
+++ b/apps/desktopgui/nbproject/project.properties
@@ -0,0 +1,68 @@
+application.desc=An anonymous communication network.
+application.homepage=http://www.i2p2.de
+application.title=I2P Desktop GUI
+application.vendor=I2P Developers
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/desktopgui.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+file.reference.i2p.jar=../../core/java/build/i2p.jar
+file.reference.router.jar=../../router/java/build/router.jar
+includes=**
+jar.compress=false
+javac.classpath=\
+ ${libs.swing-app-framework.classpath}:\
+ ${file.reference.router.jar}:\
+ ${file.reference.i2p.jar}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${libs.junit.classpath}:\
+ ${libs.junit_4.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+main.class=desktopgui.Main
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/apps/desktopgui/nbproject/project.xml b/apps/desktopgui/nbproject/project.xml
new file mode 100644
index 000000000..09409a64c
--- /dev/null
+++ b/apps/desktopgui/nbproject/project.xml
@@ -0,0 +1,19 @@
+
+
+ org.netbeans.modules.java.j2seproject
+
+
+ desktopgui
+ 1.6.5
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/desktopgui/src/META-INF/services/org.jdesktop.application.Application b/apps/desktopgui/src/META-INF/services/org.jdesktop.application.Application
new file mode 100644
index 000000000..6cd2ac1fb
--- /dev/null
+++ b/apps/desktopgui/src/META-INF/services/org.jdesktop.application.Application
@@ -0,0 +1 @@
+desktopgui.Main
\ No newline at end of file
diff --git a/apps/desktopgui/src/desktopgui/Main.java b/apps/desktopgui/src/desktopgui/Main.java
new file mode 100644
index 000000000..9d9708c8d
--- /dev/null
+++ b/apps/desktopgui/src/desktopgui/Main.java
@@ -0,0 +1,109 @@
+package desktopgui;
+
+/*
+ * Main.java
+ */
+
+
+
+import gui.Tray;
+import gui.SpeedSelector;
+import java.awt.SystemTray;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+import org.jdesktop.application.Application;
+import org.jdesktop.application.SingleFrameApplication;
+import persistence.PropertyManager;
+
+/**
+ * The main class of the application.
+ */
+public class Main extends SingleFrameApplication {
+
+ /**
+ * At startup create and show the main frame of the application.
+ */
+ @Override protected void startup() {
+ Properties props = PropertyManager.loadProps();
+
+ //First load: present screen with information (to help choose I2P settings)
+ if(props.getProperty(FIRSTLOAD).equals("true")) {
+ props.setProperty(FIRSTLOAD, "false");
+ PropertyManager.saveProps(props);
+ new SpeedSelector(); //Start speed selector GUI
+ }
+
+ if(SystemTray.isSupported()) {
+ tray = new Tray();
+ }
+ else { //Alternative if SystemTray is not supported on the platform
+ }
+ }
+
+ /**
+ * This method is to initialize the specified window by injecting resources.
+ * Windows shown in our application come fully initialized from the GUI
+ * builder, so this additional configuration is not needed.
+ */
+ @Override protected void configureWindow(java.awt.Window root) {
+ }
+
+ /**
+ * A convenient static getter for the application instance.
+ * @return the instance of Main
+ */
+ public static Main getApplication() {
+ return Application.getInstance(Main.class);
+ }
+
+ /**
+ * Main method launching the application.
+ */
+ public static void main(String[] args) {
+ System.setProperty("java.awt.headless", "false"); //Make sure I2P is running in GUI mode for our application
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (ClassNotFoundException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (InstantiationException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IllegalAccessException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (UnsupportedLookAndFeelException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ Main main = getApplication();
+ main.launchForeverLoop();
+ main.startup();
+ }
+
+ /**
+ * Avoids the app terminating because no Window is opened anymore.
+ * More info: http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown
+ */
+ public void launchForeverLoop() {
+ Runnable r = new Runnable() {
+ public void run() {
+ try {
+ Object o = new Object();
+ synchronized (o) {
+ o.wait();
+ }
+ } catch (InterruptedException ie) {
+ }
+ }
+ };
+ Thread t = new Thread(r);
+ t.setDaemon(false);
+ t.start();
+ }
+
+ private Tray tray = null;
+ ///Indicates if this is the first time the application loads
+ ///(is only true at the very start of loading the first time!)
+ private static final String FIRSTLOAD = "firstLoad";
+}
diff --git a/apps/desktopgui/src/desktopgui/resources/Main.properties b/apps/desktopgui/src/desktopgui/resources/Main.properties
new file mode 100644
index 000000000..f79fe9a00
--- /dev/null
+++ b/apps/desktopgui/src/desktopgui/resources/Main.properties
@@ -0,0 +1,11 @@
+# Application global resources
+
+Application.name = desktopgui
+Application.title = I2P Desktop GUI
+Application.version = 0.7.1
+Application.vendor = I2P Developers
+Application.homepage = http://www.i2p2.de
+Application.description = An anonymous communication network.
+Application.vendorId = I2P
+Application.id = ${Application.name}
+Application.lookAndFeel = system
diff --git a/apps/desktopgui/src/gui/SpeedSelector.form b/apps/desktopgui/src/gui/SpeedSelector.form
new file mode 100644
index 000000000..b256265de
--- /dev/null
+++ b/apps/desktopgui/src/gui/SpeedSelector.form
@@ -0,0 +1,160 @@
+
+
+
diff --git a/apps/desktopgui/src/gui/SpeedSelector.java b/apps/desktopgui/src/gui/SpeedSelector.java
new file mode 100644
index 000000000..19f487534
--- /dev/null
+++ b/apps/desktopgui/src/gui/SpeedSelector.java
@@ -0,0 +1,176 @@
+/*
+ * ProfileSelector.java
+ *
+ * Created on 3 april 2009, 13:57
+ */
+
+package gui;
+
+import java.awt.Dimension;
+import java.awt.Point;
+import java.util.Properties;
+import javax.swing.JTextField;
+import persistence.PropertyManager;
+import util.IntegerVerifier;
+
+/**
+ *
+ * @author mathias
+ */
+public class SpeedSelector extends javax.swing.JFrame {
+
+ /** Creates new form ProfileSelector */
+ public SpeedSelector() {
+ this.props = PropertyManager.getProps();
+ initComponents();
+ initComponentsCustom();
+ initSpeeds(props);
+ this.setVisible(true);
+ }
+
+ public SpeedSelector(Point point, Dimension dimension) {
+ this();
+ this.setLocation(point);
+ this.setSize(dimension);
+ }
+
+ public void initComponentsCustom() {
+ ((JTextField)uploadChoice.getEditor().getEditorComponent()).setInputVerifier(new IntegerVerifier());
+ ((JTextField)downloadChoice.getEditor().getEditorComponent()).setInputVerifier(new IntegerVerifier());
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ nextButton = new javax.swing.JButton();
+ uploadLabel = new javax.swing.JLabel();
+ downloadLabel = new javax.swing.JLabel();
+ uploadChoice = new javax.swing.JComboBox();
+ downloadChoice = new javax.swing.JComboBox();
+ kbps1 = new javax.swing.JLabel();
+ kbps2 = new javax.swing.JLabel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(SpeedSelector.class);
+ setTitle(resourceMap.getString("Form.title")); // NOI18N
+ setName("Form"); // NOI18N
+
+ nextButton.setText(resourceMap.getString("nextButton.text")); // NOI18N
+ nextButton.setName("nextButton"); // NOI18N
+ nextButton.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ nextButtonMouseClicked(evt);
+ }
+ });
+
+ uploadLabel.setText(resourceMap.getString("uploadLabel.text")); // NOI18N
+ uploadLabel.setName("uploadLabel"); // NOI18N
+
+ downloadLabel.setText(resourceMap.getString("downloadLabel.text")); // NOI18N
+ downloadLabel.setName("downloadLabel"); // NOI18N
+
+ uploadChoice.setEditable(true);
+ uploadChoice.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "100", "200", "500", "1000", "2000", "4000", "8000", "10000", "20000", "50000", "100000" }));
+ uploadChoice.setSelectedIndex(3);
+ uploadChoice.setName("uploadChoice"); // NOI18N
+
+ downloadChoice.setEditable(true);
+ downloadChoice.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "100", "200", "500", "1000", "2000", "4000", "8000", "10000", "20000", "50000", "100000" }));
+ downloadChoice.setSelectedIndex(3);
+ downloadChoice.setName("downloadChoice"); // NOI18N
+
+ kbps1.setText(resourceMap.getString("kbps1.text")); // NOI18N
+ kbps1.setName("kbps1"); // NOI18N
+
+ kbps2.setText(resourceMap.getString("kbps2.text")); // NOI18N
+ kbps2.setName("kbps2"); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(49, 49, 49)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(downloadLabel)
+ .addComponent(uploadLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(downloadChoice, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(kbps2))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(uploadChoice, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(kbps1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(nextButton)
+ .addGap(34, 34, 34))))
+ .addGap(40, 40, 40))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(67, 67, 67)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(uploadLabel)
+ .addComponent(uploadChoice, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(kbps1))
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(downloadLabel)
+ .addComponent(downloadChoice, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(kbps2))
+ .addContainerGap(173, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap(271, Short.MAX_VALUE)
+ .addComponent(nextButton)
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+private void nextButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_nextButtonMouseClicked
+ props.setProperty(SpeedSelectorConstants.MAXUPLOADCAPABLE, uploadChoice.getSelectedItem().toString());
+ props.setProperty(SpeedSelectorConstants.MAXDOWNLOADCAPABLE, downloadChoice.getSelectedItem().toString());
+ PropertyManager.saveProps(props);
+ new SpeedSelector2(this.getLocationOnScreen(), this.getSize());
+ this.dispose();
+}//GEN-LAST:event_nextButtonMouseClicked
+
+private void initSpeeds(Properties props) {
+ String up = props.getProperty(SpeedSelectorConstants.MAXUPLOADCAPABLE);
+ String down = props.getProperty(SpeedSelectorConstants.MAXDOWNLOADCAPABLE);
+
+ if(up == null)
+ props.setProperty(SpeedSelectorConstants.MAXUPLOADCAPABLE, "1000");
+ if(down == null)
+ props.setProperty(SpeedSelectorConstants.MAXDOWNLOADCAPABLE, "1000");
+
+ uploadChoice.setSelectedItem(props.getProperty(SpeedSelectorConstants.MAXUPLOADCAPABLE));
+ downloadChoice.setSelectedItem(props.getProperty(SpeedSelectorConstants.MAXDOWNLOADCAPABLE));
+}
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JComboBox downloadChoice;
+ private javax.swing.JLabel downloadLabel;
+ private javax.swing.JLabel kbps1;
+ private javax.swing.JLabel kbps2;
+ private javax.swing.JButton nextButton;
+ private javax.swing.JComboBox uploadChoice;
+ private javax.swing.JLabel uploadLabel;
+ // End of variables declaration//GEN-END:variables
+
+ Properties props;
+}
diff --git a/apps/desktopgui/src/gui/SpeedSelector2.form b/apps/desktopgui/src/gui/SpeedSelector2.form
new file mode 100644
index 000000000..2f0abc786
--- /dev/null
+++ b/apps/desktopgui/src/gui/SpeedSelector2.form
@@ -0,0 +1,116 @@
+
+
+
diff --git a/apps/desktopgui/src/gui/SpeedSelector2.java b/apps/desktopgui/src/gui/SpeedSelector2.java
new file mode 100644
index 000000000..a02ef9b53
--- /dev/null
+++ b/apps/desktopgui/src/gui/SpeedSelector2.java
@@ -0,0 +1,174 @@
+/*
+ * ProfileSelector2.java
+ *
+ * Created on 3 april 2009, 14:36
+ */
+
+package gui;
+
+import java.awt.Dimension;
+import java.awt.Point;
+import java.util.Enumeration;
+import java.util.Properties;
+import javax.swing.AbstractButton;
+import persistence.PropertyManager;
+
+/**
+ *
+ * @author mathias
+ */
+public class SpeedSelector2 extends javax.swing.JFrame {
+ Properties props;
+
+ /** Creates new form ProfileSelector2 */
+ public SpeedSelector2(Point point, Dimension dimension) {
+ this.props = PropertyManager.getProps();
+ initComponents();
+ this.setLocation(point);
+ this.setSize(dimension);
+ loadButtonSelection();
+ this.setVisible(true);
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ buttonGroup1 = new javax.swing.ButtonGroup();
+ nextButton = new javax.swing.JButton();
+ returnButton = new javax.swing.JButton();
+ questionLabel = new javax.swing.JLabel();
+ browseButton = new javax.swing.JRadioButton();
+ downloadButton = new javax.swing.JRadioButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(SpeedSelector2.class);
+ setTitle(resourceMap.getString("Form.title")); // NOI18N
+ setName("Form"); // NOI18N
+
+ nextButton.setText(resourceMap.getString("nextButton.text")); // NOI18N
+ nextButton.setName("nextButton"); // NOI18N
+ nextButton.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ nextButtonMouseClicked(evt);
+ }
+ });
+
+ returnButton.setText(resourceMap.getString("returnButton.text")); // NOI18N
+ returnButton.setName("returnButton"); // NOI18N
+ returnButton.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ returnButtonMouseClicked(evt);
+ }
+ });
+
+ questionLabel.setText(resourceMap.getString("questionLabel.text")); // NOI18N
+ questionLabel.setName("questionLabel"); // NOI18N
+
+ buttonGroup1.add(browseButton);
+ browseButton.setText(resourceMap.getString("browseButton.text")); // NOI18N
+ browseButton.setName("browseButton"); // NOI18N
+
+ buttonGroup1.add(downloadButton);
+ downloadButton.setText(resourceMap.getString("downloadButton.text")); // NOI18N
+ downloadButton.setName("downloadButton"); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap(406, Short.MAX_VALUE)
+ .addComponent(returnButton)
+ .addGap(18, 18, 18)
+ .addComponent(nextButton)
+ .addGap(74, 74, 74))
+ .addGroup(layout.createSequentialGroup()
+ .addGap(42, 42, 42)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(questionLabel)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(12, 12, 12)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(downloadButton)
+ .addComponent(browseButton))))
+ .addContainerGap(32, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(54, 54, 54)
+ .addComponent(questionLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(browseButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(downloadButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 120, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(nextButton)
+ .addComponent(returnButton))
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+private void returnButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_returnButtonMouseClicked
+ saveButtonSelection();
+ PropertyManager.saveProps(props);
+ new SpeedSelector(this.getLocationOnScreen(), this.getSize()).setVisible(true);
+ this.dispose();
+}//GEN-LAST:event_returnButtonMouseClicked
+
+private void nextButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_nextButtonMouseClicked
+ saveButtonSelection();
+ PropertyManager.saveProps(props);
+ new SpeedSelector3(this.getLocationOnScreen(), this.getSize()).setVisible(true);
+ this.dispose();
+}//GEN-LAST:event_nextButtonMouseClicked
+
+private void loadButtonSelection() {
+ Enumeration elements = buttonGroup1.getElements();
+ while(elements.hasMoreElements()) {
+ AbstractButton button = elements.nextElement();
+ if(button == null)
+ continue;
+ if(props.getProperty(SpeedSelectorConstants.USERTYPE) == null)
+ break;
+ String type = button.getText().split(":")[0];
+ if(type.equals(props.getProperty(SpeedSelectorConstants.USERTYPE))) {
+ button.setSelected(true);
+ break;
+ }
+ }
+}
+
+private void saveButtonSelection() {
+ Enumeration elements = buttonGroup1.getElements();
+ while(elements.hasMoreElements()) {
+ AbstractButton button = elements.nextElement();
+ if(button == null)
+ continue;
+ if(button.isSelected()) {
+ String type = button.getText().split(":")[0];
+ props.setProperty(SpeedSelectorConstants.USERTYPE, type);
+ break;
+ }
+ }
+}
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JRadioButton browseButton;
+ private javax.swing.ButtonGroup buttonGroup1;
+ private javax.swing.JRadioButton downloadButton;
+ private javax.swing.JButton nextButton;
+ private javax.swing.JLabel questionLabel;
+ private javax.swing.JButton returnButton;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/apps/desktopgui/src/gui/SpeedSelector3.form b/apps/desktopgui/src/gui/SpeedSelector3.form
new file mode 100644
index 000000000..419a22fc1
--- /dev/null
+++ b/apps/desktopgui/src/gui/SpeedSelector3.form
@@ -0,0 +1,223 @@
+
+
+
diff --git a/apps/desktopgui/src/gui/SpeedSelector3.java b/apps/desktopgui/src/gui/SpeedSelector3.java
new file mode 100644
index 000000000..e226f7422
--- /dev/null
+++ b/apps/desktopgui/src/gui/SpeedSelector3.java
@@ -0,0 +1,286 @@
+/*
+ * ProfileSelector3.java
+ *
+ * Created on 3 april 2009, 15:17
+ */
+
+package gui;
+
+import java.awt.Dimension;
+import java.awt.Point;
+import java.util.Properties;
+import persistence.PropertyManager;
+import router.configuration.SpeedHandler;
+import router.configuration.SpeedHelper;
+
+/**
+ *
+ * @author mathias
+ */
+public class SpeedSelector3 extends javax.swing.JFrame {
+ Properties props;
+
+ /** Creates new form ProfileSelector3 */
+ public SpeedSelector3(Point point, Dimension dimension) {
+ this.props = PropertyManager.getProps();
+ initComponents();
+ this.setLocation(point);
+ this.setSize(dimension);
+ initSpeeds();
+ this.setVisible(true);
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ finishButton = new javax.swing.JButton();
+ previousButton = new javax.swing.JButton();
+ jLabel1 = new javax.swing.JLabel();
+ uploadLabel = new javax.swing.JLabel();
+ downloadLabel = new javax.swing.JLabel();
+ uploadBurstLabel = new javax.swing.JLabel();
+ downloadBurstLabel = new javax.swing.JLabel();
+ uploadUsageLabel = new javax.swing.JLabel();
+ downloadUsageLabel = new javax.swing.JLabel();
+ uploadField = new javax.swing.JTextField();
+ uploadBurstField = new javax.swing.JTextField();
+ downloadField = new javax.swing.JTextField();
+ downloadBurstField = new javax.swing.JTextField();
+ uploadMonth = new javax.swing.JLabel();
+ downloadMonth = new javax.swing.JLabel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(SpeedSelector3.class);
+ setTitle(resourceMap.getString("Form.title")); // NOI18N
+ setName("Form"); // NOI18N
+
+ finishButton.setText(resourceMap.getString("finishButton.text")); // NOI18N
+ finishButton.setName("finishButton"); // NOI18N
+ finishButton.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ finishButtonMouseClicked(evt);
+ }
+ });
+
+ previousButton.setText(resourceMap.getString("previousButton.text")); // NOI18N
+ previousButton.setName("previousButton"); // NOI18N
+ previousButton.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ previousButtonMouseClicked(evt);
+ }
+ });
+
+ jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
+ jLabel1.setName("jLabel1"); // NOI18N
+
+ uploadLabel.setText(resourceMap.getString("uploadLabel.text")); // NOI18N
+ uploadLabel.setName("uploadLabel"); // NOI18N
+
+ downloadLabel.setText(resourceMap.getString("downloadLabel.text")); // NOI18N
+ downloadLabel.setName("downloadLabel"); // NOI18N
+
+ uploadBurstLabel.setText(resourceMap.getString("uploadBurstLabel.text")); // NOI18N
+ uploadBurstLabel.setName("uploadBurstLabel"); // NOI18N
+
+ downloadBurstLabel.setText(resourceMap.getString("downloadBurstLabel.text")); // NOI18N
+ downloadBurstLabel.setName("downloadBurstLabel"); // NOI18N
+
+ uploadUsageLabel.setText(resourceMap.getString("uploadUsageLabel.text")); // NOI18N
+ uploadUsageLabel.setName("uploadUsageLabel"); // NOI18N
+
+ downloadUsageLabel.setText(resourceMap.getString("downloadUsageLabel.text")); // NOI18N
+ downloadUsageLabel.setName("downloadUsageLabel"); // NOI18N
+
+ uploadField.setText(resourceMap.getString("uploadField.text")); // NOI18N
+ uploadField.setMinimumSize(new java.awt.Dimension(77, 27));
+ uploadField.setName("uploadField"); // NOI18N
+ uploadField.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyReleased(java.awt.event.KeyEvent evt) {
+ speedFieldKeyReleased(evt);
+ }
+ });
+
+ uploadBurstField.setText(resourceMap.getString("uploadBurstField.text")); // NOI18N
+ uploadBurstField.setMinimumSize(new java.awt.Dimension(77, 27));
+ uploadBurstField.setName("uploadBurstField"); // NOI18N
+
+ downloadField.setText(resourceMap.getString("downloadField.text")); // NOI18N
+ downloadField.setMinimumSize(new java.awt.Dimension(77, 27));
+ downloadField.setName("downloadField"); // NOI18N
+ downloadField.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyReleased(java.awt.event.KeyEvent evt) {
+ speedFieldKeyReleased(evt);
+ }
+ });
+
+ downloadBurstField.setText(resourceMap.getString("downloadBurstField.text")); // NOI18N
+ downloadBurstField.setMinimumSize(new java.awt.Dimension(77, 27));
+ downloadBurstField.setName("downloadBurstField"); // NOI18N
+
+ uploadMonth.setText(resourceMap.getString("uploadMonth.text")); // NOI18N
+ uploadMonth.setName("uploadMonth"); // NOI18N
+
+ downloadMonth.setText(resourceMap.getString("downloadMonth.text")); // NOI18N
+ downloadMonth.setName("downloadMonth"); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel1)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(uploadLabel)
+ .addComponent(uploadBurstLabel)
+ .addComponent(uploadUsageLabel))
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(uploadBurstField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(uploadField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(uploadMonth, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGap(46, 46, 46)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(downloadLabel)
+ .addComponent(downloadBurstLabel)
+ .addComponent(downloadUsageLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+ .addComponent(downloadField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(downloadMonth, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(downloadBurstField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
+ .addGap(18, 18, 18))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(previousButton)
+ .addGap(18, 18, 18)
+ .addComponent(finishButton)
+ .addGap(33, 33, 33)))
+ .addGap(400, 400, 400))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addGap(81, 81, 81)
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(uploadLabel)
+ .addComponent(downloadLabel)
+ .addComponent(uploadField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(downloadField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(uploadBurstLabel)
+ .addComponent(downloadBurstLabel)
+ .addComponent(downloadBurstField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(uploadBurstField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(uploadUsageLabel)
+ .addComponent(downloadUsageLabel)
+ .addComponent(uploadMonth)
+ .addComponent(downloadMonth))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 48, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(previousButton)
+ .addComponent(finishButton))
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+private void previousButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_previousButtonMouseClicked
+ saveSpeeds();
+ PropertyManager.saveProps(props);
+ new SpeedSelector2(this.getLocationOnScreen(), this.getSize()).setVisible(true);
+ this.dispose();
+}//GEN-LAST:event_previousButtonMouseClicked
+
+private void finishButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_finishButtonMouseClicked
+ saveSpeeds();
+ PropertyManager.saveProps(props);
+
+ int maxDownload = Integer.parseInt(props.getProperty(SpeedSelectorConstants.MAXDOWNLOAD));
+ int maxUpload = Integer.parseInt(props.getProperty(SpeedSelectorConstants.MAXUPLOAD));
+ int maxUploadBurst = Integer.parseInt(props.getProperty(SpeedSelectorConstants.MAXUPLOADBURST));
+ int maxDownloadBurst = Integer.parseInt(props.getProperty(SpeedSelectorConstants.MAXDOWNLOADBURST));
+
+ //Working in kB, not kb!
+ SpeedHandler.setInboundBandwidth(maxDownload/8);
+ SpeedHandler.setOutboundBandwidth(maxUpload/8);
+ SpeedHandler.setInboundBurstBandwidth(maxDownloadBurst);
+ SpeedHandler.setOutboundBurstBandwidth(maxUploadBurst/8);
+
+ this.dispose();
+}//GEN-LAST:event_finishButtonMouseClicked
+
+private void speedFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_speedFieldKeyReleased
+ try {
+ initUsage(uploadField.getText(), downloadField.getText());
+ }
+ catch(NumberFormatException e) {
+ return;
+ }
+}//GEN-LAST:event_speedFieldKeyReleased
+
+ protected void initSpeeds() {
+ String up = "" + SpeedHelper.calculateSpeed(
+ props.getProperty(SpeedSelectorConstants.MAXUPLOADCAPABLE), props.getProperty(SpeedSelectorConstants.USERTYPE));
+ String upBurst = "" + SpeedHelper.calculateSpeed(
+ props.getProperty(SpeedSelectorConstants.MAXUPLOADCAPABLE), props.getProperty(SpeedSelectorConstants.USERTYPE));
+ String down = "" + SpeedHelper.calculateSpeed(
+ props.getProperty(SpeedSelectorConstants.MAXDOWNLOADCAPABLE), props.getProperty(SpeedSelectorConstants.USERTYPE));
+ String downBurst = "" + SpeedHelper.calculateSpeed(
+ props.getProperty(SpeedSelectorConstants.MAXDOWNLOADCAPABLE), props.getProperty(SpeedSelectorConstants.USERTYPE));
+ String userType = props.getProperty(SpeedSelectorConstants.USERTYPE);
+
+ uploadField.setText(up);
+ uploadBurstField.setText(upBurst);
+ downloadField.setText(down);
+ downloadBurstField.setText(downBurst);
+
+ initUsage(up, down);
+ }
+
+ protected void saveSpeeds() {
+ props.setProperty(SpeedSelectorConstants.MAXUPLOAD, uploadField.getText());
+ props.setProperty(SpeedSelectorConstants.MAXUPLOADBURST, uploadBurstField.getText());
+ props.setProperty(SpeedSelectorConstants.MAXDOWNLOAD, downloadField.getText());
+ props.setProperty(SpeedSelectorConstants.MAXDOWNLOADBURST, downloadBurstField.getText());
+ }
+
+ protected void initUsage(String upload, String download) {
+ uploadMonth.setText(SpeedHelper.calculateMonthlyUsage(Integer.parseInt(upload)/8) + " GB");
+ downloadMonth.setText(SpeedHelper.calculateMonthlyUsage(Integer.parseInt(download)/8) + " GB");
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JTextField downloadBurstField;
+ private javax.swing.JLabel downloadBurstLabel;
+ private javax.swing.JTextField downloadField;
+ private javax.swing.JLabel downloadLabel;
+ private javax.swing.JLabel downloadMonth;
+ private javax.swing.JLabel downloadUsageLabel;
+ private javax.swing.JButton finishButton;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JButton previousButton;
+ private javax.swing.JTextField uploadBurstField;
+ private javax.swing.JLabel uploadBurstLabel;
+ private javax.swing.JTextField uploadField;
+ private javax.swing.JLabel uploadLabel;
+ private javax.swing.JLabel uploadMonth;
+ private javax.swing.JLabel uploadUsageLabel;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/apps/desktopgui/src/gui/SpeedSelectorConstants.java b/apps/desktopgui/src/gui/SpeedSelectorConstants.java
new file mode 100644
index 000000000..ea5e32427
--- /dev/null
+++ b/apps/desktopgui/src/gui/SpeedSelectorConstants.java
@@ -0,0 +1,25 @@
+package gui;
+
+/**
+ *
+ * @author mathias
+ */
+public class SpeedSelectorConstants {
+ ///Maximum upload speed for the internet connection
+ public static final String MAXUPLOADCAPABLE = "maxUploadCapable";
+ ///Maximum download speed for the internet connection
+ public static final String MAXDOWNLOADCAPABLE = "maxDownloadCapable";
+
+ //User profile type: what behaviour does this user have while using IP2?
+ public static final String USERTYPE = "userType";
+
+ //Maximum upload speed for I2P
+ public static final String MAXUPLOAD = "maxUpload";
+ //Maximum upload burst speed for I2P
+ public static final String MAXUPLOADBURST = "maxUploadBurst";
+
+ //Maximum download speed for I2P
+ public static final String MAXDOWNLOAD = "maxDownload";
+ //Maximum download burst speed for I2P
+ public static final String MAXDOWNLOADBURST = "maxDownloadBurst";
+}
diff --git a/apps/desktopgui/src/gui/Tray.java b/apps/desktopgui/src/gui/Tray.java
new file mode 100644
index 000000000..6ed5ea0d4
--- /dev/null
+++ b/apps/desktopgui/src/gui/Tray.java
@@ -0,0 +1,138 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package gui;
+
+import desktopgui.*;
+import java.awt.AWTException;
+import java.awt.Desktop;
+import java.awt.Image;
+import java.awt.MenuItem;
+import java.awt.Menu;
+import java.awt.PopupMenu;
+import java.awt.SystemTray;
+import java.awt.Toolkit;
+import java.awt.TrayIcon;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import router.RouterHandler;
+
+/**
+ *
+ * @author mathias
+ */
+public class Tray {
+
+ public Tray() {
+ tray = SystemTray.getSystemTray();
+ loadSystemTray();
+ }
+
+ private void loadSystemTray() {
+
+ Image image = Toolkit.getDefaultToolkit().getImage("desktopgui/resources/logo/logo.jpg");
+
+ PopupMenu popup = new PopupMenu();
+
+ //Create menu items to put in the popup menu
+ MenuItem browserLauncher = new MenuItem("Launch browser");
+ browserLauncher.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent arg0) {
+ if(Desktop.isDesktopSupported()) {
+ Desktop desktop = Desktop.getDesktop();
+ try {
+ desktop.browse(new URI("http://localhost:7657"));
+ } catch (URISyntaxException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ } catch(IOException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+
+ });
+ MenuItem howto = new MenuItem("How to use I2P");
+ howto.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent arg0) {
+ if(Desktop.isDesktopSupported()) {
+ Desktop desktop = Desktop.getDesktop();
+ try {
+ File f = new File("desktopgui/resources/howto/howto.html");
+ desktop.browse(new URI("file://" + f.getAbsolutePath()));
+ } catch (URISyntaxException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ } catch(IOException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+
+ });
+ Menu config = new Menu("Configuration");
+ MenuItem speedConfig = new MenuItem("Speed");
+ speedConfig.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent arg0) {
+ (new SpeedSelector()).setVisible(true);
+ }
+
+ });
+ MenuItem advancedConfig = new MenuItem("Advanced Configuration");
+ advancedConfig.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent arg0) {
+ if(Desktop.isDesktopSupported()) {
+ Desktop desktop = Desktop.getDesktop();
+ try {
+ desktop.browse(new URI("http://localhost:7657/config.jsp"));
+ } catch (URISyntaxException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ } catch(IOException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+
+ });
+ MenuItem shutdown = new MenuItem("Shutdown I2P");
+ shutdown.addActionListener(new ActionListener() {
+
+ public void actionPerformed(ActionEvent arg0) {
+ RouterHandler.setStatus(RouterHandler.SHUTDOWN_GRACEFULLY);
+ }
+
+ });
+
+ //Add menu items to popup menu
+ popup.add(browserLauncher);
+ popup.add(howto);
+
+ config.add(speedConfig);
+ config.add(advancedConfig);
+ popup.add(config);
+
+ popup.add(shutdown);
+
+ //Add tray icon
+ trayIcon = new TrayIcon(image, "I2P: the anonymous network", popup);
+ try {
+ tray.add(trayIcon);
+ } catch (AWTException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ private SystemTray tray = null;
+ private TrayIcon trayIcon = null;
+
+}
diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector.properties b/apps/desktopgui/src/gui/resources/SpeedSelector.properties
new file mode 100644
index 000000000..1a476d874
--- /dev/null
+++ b/apps/desktopgui/src/gui/resources/SpeedSelector.properties
@@ -0,0 +1,7 @@
+
+Form.title=I2P Configuration
+nextButton.text=Next
+uploadLabel.text=What is your maximum upload speed?
+downloadLabel.text=What is your maximum download speed?
+kbps1.text=kbit/second
+kbps2.text=kbit/second
diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector2.properties b/apps/desktopgui/src/gui/resources/SpeedSelector2.properties
new file mode 100644
index 000000000..704d9909e
--- /dev/null
+++ b/apps/desktopgui/src/gui/resources/SpeedSelector2.properties
@@ -0,0 +1,6 @@
+returnButton.text=Previous
+Form.title=I2P Configuration
+questionLabel.text=Which of these descriptions fits you best?
+browseButton.text=Browsing: I want to use I2P to browse websites anonymously, no heavy usage.
+downloadButton.text=Downloading: I want to use I2P for downloads and filesharing, heavy usage.
+nextButton.text=Next
diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector3.properties b/apps/desktopgui/src/gui/resources/SpeedSelector3.properties
new file mode 100644
index 000000000..49ee18ba0
--- /dev/null
+++ b/apps/desktopgui/src/gui/resources/SpeedSelector3.properties
@@ -0,0 +1,16 @@
+Form.title=I2P Configuration
+jLabel1.text=The profile information your entered, indicates that these are your optimal settings:
+previousButton.text=Previous
+finishButton.text=Finish
+uploadLabel.text=Upload Speed:
+uploadBurstLabel.text=Burst Upload Speed:
+downloadLabel.text=Download Speed:
+downloadBurstLabel.text=Burst Download Speed:
+uploadUsageLabel.text=Monthy upload usage:
+downloadUsageLabel.text=Monthy Download Usage:
+uploadField.text=jTextField1
+uploadBurstField.text=jTextField2
+uploadMonth.text=jLabel8
+downloadMonth.text=jLabel9
+downloadField.text=jTextField4
+downloadBurstField.text=jTextField5
diff --git a/apps/desktopgui/src/persistence/PropertyManager.java b/apps/desktopgui/src/persistence/PropertyManager.java
new file mode 100644
index 000000000..bacbf348a
--- /dev/null
+++ b/apps/desktopgui/src/persistence/PropertyManager.java
@@ -0,0 +1,72 @@
+package persistence;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author mathias
+ */
+public class PropertyManager {
+
+ public static void setProps(Properties props) {
+ PropertyManager.props = props;
+ }
+
+ public static Properties getProps() {
+ return props;
+ }
+
+ public static Properties loadProps() {
+ Properties defaultProps = new Properties();
+ defaultProps.setProperty("firstLoad", "true");
+
+ // create application properties with default
+ Properties applicationProps = new Properties(defaultProps);
+
+ // now load properties from last invocation
+ FileInputStream in;
+ try {
+ in = new FileInputStream(PROPSLOCATION);
+ applicationProps.load(in);
+ in.close();
+ } catch (FileNotFoundException ex) {
+ //Nothing serious, just means it's being loaded for the first time.
+ } catch(IOException ex) {
+ Logger.getLogger(PropertyManager.class.getName()).log(Level.INFO, null, ex);
+ }
+ props = applicationProps;
+ return applicationProps;
+ }
+
+ public static void saveProps(Properties props) {
+ FileOutputStream out;
+ try {
+ File d = new File(PROPSDIRECTORY);
+ if(!d.exists())
+ d.mkdir();
+ File f = new File(PROPSLOCATION);
+ if(!f.exists())
+ f.createNewFile();
+ out = new FileOutputStream(f);
+ props.store(out, PROPSLOCATION);
+ } catch (FileNotFoundException ex) {
+ Logger.getLogger(PropertyManager.class.getName()).log(Level.SEVERE, null, ex);
+ } catch(IOException ex) {
+ Logger.getLogger(PropertyManager.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ private static Properties props;
+
+ ///Location where we store the Application Properties
+ public static final String PROPSDIRECTORY = "desktopgui";
+ public static final String PROPSFILENAME = "appProperties";
+ public static final String PROPSLOCATION = PROPSDIRECTORY + File.separator + PROPSFILENAME;
+}
diff --git a/apps/desktopgui/src/router/RouterHandler.java b/apps/desktopgui/src/router/RouterHandler.java
new file mode 100644
index 000000000..0752f877b
--- /dev/null
+++ b/apps/desktopgui/src/router/RouterHandler.java
@@ -0,0 +1,38 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package router;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.i2p.router.RouterContext;
+
+/**
+ *
+ * @author mathias
+ */
+public class RouterHandler {
+ public static final int SHUTDOWN_GRACEFULLY = 0;
+ public static void setStatus(int status) {
+ if(status == SHUTDOWN_GRACEFULLY) {
+ Thread t = new Thread(new Runnable() {
+
+ public void run() {
+ RouterContext context = RouterHelper.getContext();
+ context.router().shutdownGracefully();
+ while(context.router().getShutdownTimeRemaining()>0)
+ try {
+ Thread.sleep(context.router().getShutdownTimeRemaining());
+ } catch (InterruptedException ex) {
+ Logger.getLogger(RouterHandler.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ System.exit(0);
+ }
+
+ });
+ t.start();
+ }
+ }
+}
diff --git a/apps/desktopgui/src/router/RouterHelper.java b/apps/desktopgui/src/router/RouterHelper.java
new file mode 100644
index 000000000..c5fc78e95
--- /dev/null
+++ b/apps/desktopgui/src/router/RouterHelper.java
@@ -0,0 +1,13 @@
+package router;
+
+import net.i2p.router.RouterContext;
+
+/**
+ *
+ * @author mathias
+ */
+public class RouterHelper {
+ public static RouterContext getContext() {
+ return (RouterContext) RouterContext.listContexts().get(0);
+ }
+}
diff --git a/apps/desktopgui/src/router/configuration/SpeedHandler.java b/apps/desktopgui/src/router/configuration/SpeedHandler.java
new file mode 100644
index 000000000..235790792
--- /dev/null
+++ b/apps/desktopgui/src/router/configuration/SpeedHandler.java
@@ -0,0 +1,34 @@
+package router.configuration;
+
+import net.i2p.router.RouterContext;
+import net.i2p.router.transport.FIFOBandwidthRefiller;
+import router.RouterHelper;
+
+/**
+ *
+ * @author mathias
+ */
+public class SpeedHandler {
+
+ public static void setInboundBandwidth(int kbytes) {
+ context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH, "" + kbytes);
+ context.router().saveConfig();
+ }
+
+ public static void setOutboundBandwidth(int kbytes) {
+ context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH, "" + kbytes);
+ context.router().saveConfig();
+ }
+
+ public static void setInboundBurstBandwidth(int kbytes) {
+ context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH, "" + kbytes);
+ context.router().saveConfig();
+ }
+
+ public static void setOutboundBurstBandwidth(int kbytes) {
+ context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH, "" + kbytes);
+ context.router().saveConfig();
+ }
+
+ private static final RouterContext context = RouterHelper.getContext();
+}
diff --git a/apps/desktopgui/src/router/configuration/SpeedHelper.java b/apps/desktopgui/src/router/configuration/SpeedHelper.java
new file mode 100644
index 000000000..1cce2f9c0
--- /dev/null
+++ b/apps/desktopgui/src/router/configuration/SpeedHelper.java
@@ -0,0 +1,28 @@
+package router.configuration;
+
+/**
+ *
+ * @author mathias
+ */
+public class SpeedHelper {
+ public static final String USERTYPE_BROWSING = "Browsing";
+ public static final String USERTYPE_DOWNLOADING = "Downloading";
+
+ public static int calculateSpeed(String capable, String profile) {
+ int capableSpeed = Integer.parseInt(capable);
+ int advisedSpeed = capableSpeed;
+ if(capableSpeed > 1000) {
+ if(profile.equals(USERTYPE_BROWSING)) //Don't overdo usage for people just wanting to browse (we don't want to drive them away due to resource hogging)
+ advisedSpeed *= 0.6;
+ else if(profile.equals(USERTYPE_DOWNLOADING))
+ advisedSpeed *= 0.8;
+ }
+ else
+ advisedSpeed *= 0.6; //Lower available bandwidth: don't hog all the bandwidth
+ return advisedSpeed;
+ }
+
+ public static int calculateMonthlyUsage(int kbytes) {
+ return (kbytes*3600*24*31)/1000000;
+ }
+}
diff --git a/apps/desktopgui/src/util/IntegerVerifier.java b/apps/desktopgui/src/util/IntegerVerifier.java
new file mode 100644
index 000000000..74f87961d
--- /dev/null
+++ b/apps/desktopgui/src/util/IntegerVerifier.java
@@ -0,0 +1,32 @@
+package util;
+
+import javax.swing.InputVerifier;
+import javax.swing.JComponent;
+import javax.swing.JTextField;
+
+/**
+ *
+ * @author mathias
+ */
+
+public class IntegerVerifier extends InputVerifier {
+
+ @Override
+ public boolean verify(JComponent arg0) {
+ JTextField jtf = (JTextField) arg0;
+ return verify(jtf.getText());
+ }
+
+ @Override
+ public boolean shouldYieldFocus(JComponent input) {
+ return verify(input);
+ }
+
+ public static boolean verify(String s) {
+ for(int i=0;i '9' || s.charAt(i) < '0')
+ return false;
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/build.xml b/build.xml
index ef84b2aab..26254cd15 100644
--- a/build.xml
+++ b/build.xml
@@ -37,6 +37,7 @@
+
@@ -104,6 +105,7 @@
+
@@ -214,6 +216,13 @@
+
+
+
+
+
+
+
diff --git a/installer/resources/wrapper.config b/installer/resources/wrapper.config
index 4d09ba12c..42958ba77 100644
--- a/installer/resources/wrapper.config
+++ b/installer/resources/wrapper.config
@@ -54,6 +54,10 @@ wrapper.java.classpath.17=lib/systray.jar
wrapper.java.classpath.18=lib/systray4j.jar
# BOB
wrapper.java.classpath.19=lib/BOB.jar
+# desktopgui
+wrapper.java.classpath.20=lib/appframework.jar
+wrapper.java.classpath.21=lib/swing-worker.jar
+wrapper.java.classpath.22=lib/desktopgui.jar
# Java Library Path (location of Wrapper.DLL or libwrapper.so)
wrapper.java.library.path.1=.