diff --git a/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java b/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java
index 732b814a7663e86262ad540ecfd5b1d327d2c231..e418c8640ca491bd85fc9c7e9be3ce1c291f03a9 100644
--- a/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java
+++ b/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java
@@ -1,6 +1,7 @@
 package net.i2p.router.news;
 
 import java.util.List;
+import net.i2p.util.VersionComparator;
 
 /**
  *  The update metadata.
@@ -15,14 +16,41 @@ public class NewsMetadata {
     public String feedID;
     public long feedUpdated;
 
-    // I2P update metadata
-    public long date;
-    public String minVersion;
-    public String minJavaVersion;
-    public String i2pVersion;
-    public String sudTorrent;
-    public String su2Torrent;
-    public String su3Torrent;
-    public List<String> su3Clearnet;
-    public List<String> su3SSL;
+    // I2P metadata
+    public List<Release> releases;
+
+    public static class Release implements Comparable<Release> {
+        public long date;
+        public String minVersion;
+        public String minJavaVersion;
+        public String i2pVersion;
+        public List<Update> updates;
+
+        @Override
+        public int compareTo(Release other) {
+            // Sort latest version first.
+            return VersionComparator.comp(other.i2pVersion, i2pVersion);
+        }
+    }
+
+    public static class Update implements Comparable<Update> {
+        public String type;
+        public List<String> torrent;
+        public List<String> clearnet;
+        public List<String> ssl;
+
+        @Override
+        public int compareTo(Update other) {
+            return Integer.compare(getTypeOrder(), other.getTypeOrder());
+        }
+
+        protected int getTypeOrder() {
+            if ("su3".equalsIgnoreCase(type))
+                return 1;
+            else if ("su2".equalsIgnoreCase(type))
+                return 2;
+            else
+                return 3;
+        }
+    }
 }
diff --git a/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java b/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java
index f3b01bdd9ee81cd7fa3bd074ab7c3fa77165f657..e643643ce8ddb89536c254fda68001053978f87b 100644
--- a/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java
+++ b/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java
@@ -15,6 +15,7 @@ import java.util.Set;
 
 import net.i2p.I2PAppContext;
 import net.i2p.util.Log;
+
 import org.cybergarage.util.Debug;
 import org.cybergarage.xml.Attribute;
 import org.cybergarage.xml.Node;
@@ -169,38 +170,63 @@ public class NewsXMLParser {
             }
         }
 
-        Node r = feed.getNode("i2p:release");
-        if (r == null)
+        List<NewsMetadata.Release> releases = new ArrayList<NewsMetadata.Release>();
+        List<Node> releaseNodes = getNodes(feed, "i2p:release");
+        if (releaseNodes.size() == 0)
             throw new I2PParserException("no release data in XML");
-        // release attributes
-        String a = r.getAttributeValue("date");
-        if (a.length() > 0) {
-            long time = RFC3339Date.parse3339Date(a);
-            if (time > 0)
-                rv.date = time;
-        }
-        a = r.getAttributeValue("minVersion");
-        if (a.length() > 0)
-            rv.minVersion = a;
-        a = r.getAttributeValue("minJavaVersion");
-        if (a.length() > 0)
-            rv.minJavaVersion = a;
-        // release nodes
-        n = r.getNode("i2p:version");
-        if (n != null)
-            rv.i2pVersion = n.getValue();
-        List<Node> urls = getNodes(r, "i2p:torrent");
-        for (Node t : urls) {
-            // returns "" for none
-            String href = t.getAttributeValue("href");
-            if (href.length() > 0) {
-                String type = t.getAttributeValue("type");
-                if (type.equals("su2"))
-                    rv.su2Torrent = href;
-                else if (type.equals("su3"))
-                    rv.su3Torrent = href;
+        for (Node r : releaseNodes) {
+            NewsMetadata.Release release = new NewsMetadata.Release();
+            // release attributes
+            String a = r.getAttributeValue("date");
+            if (a.length() > 0) {
+                long time = RFC3339Date.parse3339Date(a);
+                if (time > 0)
+                    release.date = time;
+            }
+            a = r.getAttributeValue("minVersion");
+            if (a.length() > 0)
+                release.minVersion = a;
+            a = r.getAttributeValue("minJavaVersion");
+            if (a.length() > 0)
+                release.minJavaVersion = a;
+            // release nodes
+            n = r.getNode("i2p:version");
+            if (n != null)
+                release.i2pVersion = n.getValue();
+
+            List<NewsMetadata.Update> updates = new ArrayList<NewsMetadata.Update>();
+            List<Node> updateNodes = getNodes(r, "i2p:update");
+            for (Node u : updateNodes) {
+                // returns "" for none
+                String type = u.getAttributeValue("type");
+                if (type.length() > 0) {
+                    NewsMetadata.Update update = new NewsMetadata.Update();
+                    update.type = type;
+                    int totalSources = 0;
+
+                    List<String> torrents = new ArrayList<String>();
+                    List<Node> torrentNodes = getNodes(u, "i2p:torrent");
+                    for (Node t : torrentNodes) {
+                        // returns "" for none
+                        String href = t.getAttributeValue("href");
+                        if (href.length() > 0) {
+                            torrents.add(href);
+                        }
+                    }
+                    update.torrent = torrents;
+                    totalSources += torrents.size();
+
+                    if (totalSources == 0)
+                        throw new I2PParserException("no sources for update type " + type);
+                    updates.add(update);
+                }
             }
+            Collections.sort(updates);
+            release.updates = updates;
+            releases.add(release);
         }
+        Collections.sort(releases);
+        rv.releases = releases;
 
         return rv;
     }
@@ -388,8 +414,9 @@ public class NewsXMLParser {
             parser.parse(new File(args[0]));
             NewsMetadata ud = parser.getMetadata();
             List<NewsEntry> entries = parser.getEntries();
-            System.out.println("Latest version is " + ud.i2pVersion);
-            System.out.println("Release timestamp: " + ud.date);
+            NewsMetadata.Release latestRelease = ud.releases.get(0);
+            System.out.println("Latest version is " + latestRelease.i2pVersion);
+            System.out.println("Release timestamp: " + latestRelease.date);
             System.out.println("Feed timestamp: " + ud.feedUpdated);
             System.out.println("Found " + entries.size() + " news entries");
             for (int i = 0; i < entries.size(); i++) {
diff --git a/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java b/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java
index a17926ed3a3320ca0183c915fb52eae8e23e50c8..063068cdcae3ff59f53d34be1adf0d6eb551939d 100644
--- a/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java
+++ b/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java
@@ -459,22 +459,35 @@ class NewsFetcher extends UpdateRunner {
      */
     private void outputOldNewsXML(NewsMetadata data, List<NewsEntry> entries,
                                   String sudVersion, String signingKeyName, File to) throws IOException {
+        NewsMetadata.Release latestRelease = data.releases.get(0);
         Writer out = null;
         try {
             out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(to), "UTF-8"));
             out.write("<!--\n");
             // update metadata in old format
             out.write("<i2p.release ");
-            if (data.i2pVersion != null)
-                out.write(" version=\"" + data.i2pVersion + '"');
-            if (data.minVersion != null)
-                out.write(" minVersion=\"" + data.minVersion + '"');
-            if (data.minJavaVersion != null)
-                out.write(" minJavaVersion=\"" + data.minJavaVersion + '"');
-            if (data.su2Torrent != null)
-                out.write(" su2Torrent=\"" + data.su2Torrent + '"');
-            if (data.su3Torrent != null)
-                out.write(" su3Torrent=\"" + data.su3Torrent + '"');
+            if (latestRelease.i2pVersion != null)
+                out.write(" version=\"" + latestRelease.i2pVersion + '"');
+            if (latestRelease.minVersion != null)
+                out.write(" minVersion=\"" + latestRelease.minVersion + '"');
+            if (latestRelease.minJavaVersion != null)
+                out.write(" minJavaVersion=\"" + latestRelease.minJavaVersion + '"');
+            String su3Torrent = "";
+            String su2Torrent = "";
+            for (NewsMetadata.Update update : latestRelease.updates) {
+                if (update.torrent.size() > 0) {
+                    // Only take the first torrent magnet
+                    // TODO handle multiple torrent magnetss
+                    if ("su3".equals(update.type) && su3Torrent.isEmpty())
+                        su3Torrent = update.torrent.get(0);
+                    else if ("su2".equals(update.type) && su2Torrent.isEmpty())
+                        su2Torrent = update.torrent.get(0);
+                }
+            }
+            if (!su2Torrent.isEmpty())
+                out.write(" su2Torrent=\"" + su2Torrent + '"');
+            if (!su3Torrent.isEmpty())
+                out.write(" su3Torrent=\"" + su3Torrent + '"');
             out.write("/>\n");
             // su3 and feed metadata for debugging
             out.write("** News version:\t" + DataHelper.stripHTML(sudVersion) + '\n');