Changeset d4b0bfd


Ignore:
Timestamp:
Dec 11, 2010 6:06:01 PM (9 years ago)
Author:
z3d <z3d@…>
Branches:
master
Children:
7c63866
Parents:
c3597cf (diff), 0be2ca8b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge of '4be12c91831cc6b24ef6fcf16af9cbb9fa32069d'

and 'c578a1847c62244cfc8308021014c94afef01606'

Files:
15 deleted
24 edited

Legend:

Unmodified
Added
Removed
  • apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java

    rc3597cf rd4b0bfd  
    180180            _config.setProperty(PROP_STARTUP_DELAY, "" + DEFAULT_STARTUP_DELAY);
    181181        if (!_config.containsKey(PROP_THEME))
    182             _config.setProperty(PROP_THEME, "" + DEFAULT_THEME);
     182            _config.setProperty(PROP_THEME, DEFAULT_THEME);
    183183        updateConfig();
    184184    }
     
    199199            String[] themes = null;
    200200            // "docs/themes/snark/"
    201             String fsc = new String(""+File.separatorChar);
    202             String look = _context.getBaseDir() + fsc + "docs" + fsc +"themes" + fsc + "snark" + fsc;
     201            File dir = new File(_context.getBaseDir(), "docs/themes/snark");
    203202            FileFilter fileFilter = new FileFilter() { public boolean accept(File file) { return file.isDirectory(); } };
    204203            // Walk the themes dir, collecting the theme names, and append them to the map
    205             File dir = new File(look);
    206204            File[] dirnames = dir.listFiles(fileFilter);
    207205            if (dirnames != null) {
     
    272270    public void updateConfig(String dataDir, boolean autoStart, String startDelay, String seedPct, String eepHost,
    273271                             String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
    274                              String upLimit, String upBW, boolean useOpenTrackers, String openTrackers, String Theme) {
     272                             String upLimit, String upBW, boolean useOpenTrackers, String openTrackers, String theme) {
    275273        boolean changed = false;
    276274        //if (eepHost != null) {
     
    435433            }
    436434        }
    437         if (Theme != null) {
    438             if(!Theme.equals(_config.getProperty(PROP_THEME))) {
    439                 _config.setProperty(PROP_THEME, Theme +"");
    440                 addMessage (Theme+(_(" theme locked and loaded.")));
     435        if (theme != null) {
     436            if(!theme.equals(_config.getProperty(PROP_THEME))) {
     437                _config.setProperty(PROP_THEME, theme);
     438                addMessage(_("{0} theme loaded, return to main i2psnark page to view.", theme));
    441439                changed = true;
    442440            }
     
    936934//       , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/"
    937935//       , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/"
    938        "POSTMAN", "http://tracker2.postman.i2p/announce.php=http://tracker2.postman.i2p/"
    939        ,"WELTERDE", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
     936       "Postman", "http://tracker2.postman.i2p/announce.php=http://tracker2.postman.i2p/"
     937       ,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
    940938//       , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
    941939    };
  • apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java

    rc3597cf rd4b0bfd  
    3232import net.i2p.util.I2PAppThread;
    3333import net.i2p.util.Log;
     34import net.i2p.util.SecureFileOutputStream;
    3435
    3536import org.klomp.snark.MetaInfo;
     
    5657    private static long _nonce;
    5758    private Resource _resourceBase;
     59    private String _themePath;
     60    private String _imgPath;
    5861   
    5962    public static final String PROP_CONFIG_FILE = "i2psnark.configFile";
     
    125128            return;
    126129        }
     130        _themePath = "/themes/snark/" + _manager.getTheme() + '/';
     131        _imgPath = _themePath + "images/";
    127132        // this is the part after /i2psnark
    128133        String path = req.getServletPath();
    129134        boolean isConfigure = "/configure".equals(path);
    130135        // index.jsp doesn't work, it is grabbed by the war handler before here
    131         if (!(path == null || path.equals("/") || path.equals("/index.jsp") || path.equals("/index.html") || isConfigure)) {
     136        if (!(path == null || path.equals("/") || path.equals("/index.jsp") || path.equals("/index.html") || path.equals("/_post") || isConfigure)) {
    132137            if (path.endsWith("/")) {
    133138                // bypass the horrid Resource.getListHTML()
     
    159164       
    160165        String nonce = req.getParameter("nonce");
    161         if ( (nonce != null) && (nonce.equals(String.valueOf(_nonce))) )
    162             processRequest(req);
     166        if (nonce != null) {
     167            if (nonce.equals(String.valueOf(_nonce)))
     168                processRequest(req);
     169            else  // nonce is constant, shouldn't happen
     170                _manager.addMessage("Please retry form submission (bad nonce)");
     171        }
    163172       
    164173        String peerParam = req.getParameter("p");
     
    171180
    172181        PrintWriter out = resp.getWriter();
    173         out.write("<html>\n" +
    174                   "<head><link rel=\"shortcut icon\" href=\"/themes/snark/" + _manager.getTheme() + "/favicon.ico\">\n" +
     182        out.write(DOCTYPE + "<html>\n" +
     183                  "<head><link rel=\"shortcut icon\" href=\"" + _themePath + "favicon.ico\">\n" +
    175184                  "<title>");
    176185        out.write(_("I2PSnark - Anonymous BitTorrent Client"));
     
    181190        // we want it to go to the base URI so we don't refresh with some funky action= value
    182191        if (!isConfigure)
    183             out.write("<meta http-equiv=\"refresh\" content=\"60;" + req.getRequestURI() + peerString + "\">\n");
    184         out.write(HEADER_A + _manager.getTheme() + HEADER_B);
     192            out.write("<meta http-equiv=\"refresh\" content=\"60;/i2psnark/" + peerString + "\">\n");
     193        out.write(HEADER_A + _themePath + HEADER_B);
    185194        out.write("</head><body>");
    186195        out.write("<center>");
     
    189198            out.write(_("Torrents"));
    190199            out.write("\" class=\"snarkRefresh\">");
    191             out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/arrow_refresh.png\"> ");
     200            out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "arrow_refresh.png\">&nbsp;&nbsp;");
    192201            out.write(_("I2PSnark"));
    193202            out.write("</a>");
    194203        } else {
    195             out.write("<div class=\"snarknavbar\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\"");
     204            out.write("<div class=\"snarknavbar\"><a href=\"/i2psnark/" + peerString + "\" title=\"");
    196205            out.write(_("Refresh page"));
    197206            out.write("\" class=\"snarkRefresh\">");
    198             out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/arrow_refresh.png\"> ");
     207            out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "arrow_refresh.png\">&nbsp;&nbsp;");
    199208            out.write(_("I2PSnark"));
    200209            out.write("</a> <a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\" target=\"_blank\">");
     
    245254        boolean isForm = _manager.util().connected() || !snarks.isEmpty();
    246255        if (isForm) {
    247             out.write("<form action=\"");
    248             out.write(uri);
    249             out.write("\" method=\"POST\">\n");
     256            out.write("<form action=\"_post\" method=\"POST\">\n");
    250257            out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
    251258            // don't lose peer setting
     
    254261        }
    255262        out.write(TABLE_HEADER);
    256         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/status.png\"");
    257         out.write(" title=\"");
     263        out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "status.png\" > ");
    258264        out.write(_("Status"));
    259         out.write("\"> ");
    260 //        out.write(_("Status"));
    261265        if (_manager.util().connected() && !snarks.isEmpty()) {
    262             out.write(" <a href=\"");
    263             out.write(req.getRequestURI());
     266            out.write(" <a href=\"/i2psnark/");
    264267            if (peerParam != null) {
    265268                out.write("\">");
    266                 out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/showpeers.png\" title=\"");
    267                 out.write(_("Hide All Attached Peers [connected/total in swarm]"));
     269                out.write("<img border=\"0\" src=\"" + _imgPath + "hidepeers.png\" title=\"");
     270                out.write(_("Hide Peers"));
    268271                out.write("\" alt=\"");
    269272                out.write(_("Hide Peers"));
     
    271274            } else {
    272275                out.write("?p=1\">");
    273                 out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/hidepeers.png\" title=\"");
    274                 out.write(_("Show All Attached Peers [connected/total in swarm]"));
     276                out.write("<img border=\"0\" src=\"" + _imgPath + "showpeers.png\" title=\"");
     277                out.write(_("Show Peers"));
    275278                out.write("\" alt=\"");
    276279                out.write(_("Show Peers"));
     
    279282            out.write("</a><br>\n");
    280283        }
    281         out.write("</th>\n<th align=\"left\">");
    282 //        out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/torrent.png\"\">");
    283         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_torrent.png\" title=\"");
    284         out.write(_("Loaded Torrents"));
    285         out.write("\">");
    286 //        out.write(_("Torrent"));
    287         out.write("</th>\n<th align=\"center\">");
    288         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_eta.png\" title=\"");
    289         out.write(_("Estimated Download Time"));
    290         out.write("\">");  // space here would look better but nbsp is too big and thinsp breaks
    291  //       out.write(_("ETA"));
    292         out.write("</th>\n<th align=\"center\">");
    293         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_rx.png\" title=\"");
     284        out.write("</th>\n<th colspan=\"3\" align=\"left\">");
     285        out.write("<img border=\"0\" src=\"" + _imgPath + "torrent.png\" alt=\"\">");
     286        out.write(_("Torrent"));
     287        out.write("</th>\n<th align=\"right\">");
     288        if (_manager.util().connected() && !snarks.isEmpty()) {
     289            out.write("<img border=\"0\" src=\"" + _imgPath + "eta.png\" alt=\"\" title=\"");
     290            out.write(_("Estimated time remaining"));
     291            out.write("\">");
     292            out.write(_("ETA"));
     293        }
     294        out.write("</th>\n<th align=\"right\">");
     295        out.write("<img border=\"0\" src=\"" + _imgPath + "head_rx.png\" alt=\"\" title=\"");
    294296        out.write(_("Downloaded"));
    295297        out.write("\">");
    296 //        out.write(_("RX"));
     298        out.write(_("RX"));
     299        out.write("</th>\n<th align=\"right\">");
     300        if (_manager.util().connected() && !snarks.isEmpty()) {
     301            out.write("<img border=\"0\" src=\"" + _imgPath + "head_tx.png\" alt=\"\" title=\"");
     302            out.write(_("Uploaded"));
     303            out.write("\">");
     304            out.write(_("TX"));
     305        }
     306        out.write("</th>\n<th align=\"right\">");
     307        if (_manager.util().connected() && !snarks.isEmpty()) {
     308            out.write("<img border=\"0\" src=\"" + _imgPath + "head_rxspeed.png\" title=\"");
     309            out.write(_("Down Rate"));
     310            out.write("\" alt=\"");
     311            out.write(_("RX"));
     312            out.write(" \">");
     313            out.write(_("Rate"));
     314        }
     315        out.write("</th>\n<th align=\"right\">");
     316        if (_manager.util().connected() && !snarks.isEmpty()) {
     317            out.write("<img border=\"0\" src=\"" + _imgPath + "head_txspeed.png\" title=\"");
     318            out.write(_("Up Rate"));
     319            out.write("\" alt=\"");
     320            out.write(_("TX"));
     321            out.write(" \">");
     322            out.write(_("Rate"));
     323        }
    297324        out.write("</th>\n<th align=\"center\">");
    298         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_tx.png\" title=\"");
    299         out.write(_("Uploaded"));
    300         out.write("\">");
    301 //        out.write(_("TX"));
    302         out.write("</th>\n<th align=\"center\">");
    303         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_rxspeed.png\" title=\"");
    304         out.write(_("Down Rate"));
    305         out.write("\">");
    306 //        out.write(_("Rate"));
    307         out.write("</th>\n<th align=\"center\">");
    308         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_txspeed.png\" title=\"");
    309         out.write(_("Up Rate"));
    310         out.write("\">");
    311 //        out.write(_("Rate"));
    312         out.write("</th>\n");
    313         out.write("<th align=\"center\">");
     325
     326        // Opera and text-mode browsers: no &thinsp; and no input type=image values submitted
     327        String ua = req.getHeader("User-Agent");
     328        boolean isDegraded = ua != null && (ua.startsWith("Opera") || ua.startsWith("Lynx") ||
     329                                            ua.startsWith("ELinks") || ua.startsWith("Dillo"));
     330
    314331        if (_manager.util().connected()) {
    315             out.write("<input type=\"image\" name=\"action\" value=\"StopAll\" title=\"");
     332            if (isDegraded)
     333                out.write("<a href=\"/i2psnark/?action=StopAll&amp;nonce=" + _nonce + "\"><img title=\"");
     334            else
     335                out.write("<input type=\"image\" name=\"action\" value=\"StopAll\" title=\"");
    316336            out.write(_("Stop all torrents and the I2P tunnel"));
    317             out.write("\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stop_all.png\" alt=\"");
     337            out.write("\" src=\"" + _imgPath + "stop_all.png\" alt=\"");
    318338            out.write(_("Stop All"));
    319339            out.write("\">");
     340            if (isDegraded)
     341                out.write("</a>");
    320342        } else if (!snarks.isEmpty()) {
    321             out.write("<input type=\"image\" name=\"action\" value=\"StartAll\" title=\"");
     343            if (isDegraded)
     344                out.write("<a href=\"/i2psnark/?action=StartAll&amp;nonce=" + _nonce + "\"><img title=\"");
     345            else
     346                out.write("<input type=\"image\" name=\"action\" value=\"StartAll\" title=\"");
    322347            out.write(_("Start all torrents and the I2P tunnel"));
    323             out.write("\" src=\"/themes/snark/" + _manager.getTheme() + "/images/start_all.png\" alt=\"");
     348            out.write("\" src=\"" + _imgPath + "start_all.png\" alt=\"");
    324349            out.write(_("Start All"));
    325350            out.write("\">");
     351            if (isDegraded)
     352                out.write("</a>");
    326353        } else {
    327354            out.write("&nbsp;");
     
    332359            boolean showDebug = "2".equals(peerParam);
    333360            boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam);
    334             displaySnark(out, snark, uri, i, stats, showPeers, showDebug);
     361            displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, showDebug);
    335362        }
    336363
     
    338365            out.write("<tr class=\"snarkTorrentNoneLoaded\">" +
    339366                      "<td class=\"snarkTorrentNoneLoaded\"" +
    340                       " colspan=\"8\"><i>");
     367                      " colspan=\"11\"><i>");
    341368            out.write(_("No torrents loaded."));
    342369            out.write("</i></td></tr>\n");
    343370        } else if (snarks.size() > 1) {
    344371            out.write("<tfoot><tr>\n" +
    345 //                      "    <th align=\"left\" colspan=\"2\">");
    346                       "    <th align=\"left\">");
    347 //            out.write(_("Totals"));
    348 //            out.write(" &raquo;&nbsp;");
    349             out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/status.png\"");
    350             out.write(" title=\"");
     372                      "    <th align=\"left\" colspan=\"6\">");
    351373            out.write(_("Totals"));
    352             out.write("\">");
    353             out.write("&thinsp;");
    354 //            out.write(ngettext("1 connected peer", "{0} connected peers", (int) stats[4]));
    355             out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_peers.png\"");
    356             out.write(" title=\"");
     374            out.write(":&nbsp;");
     375            out.write(ngettext("1 torrent", "{0} torrents", snarks.size()));
     376            out.write(", ");
     377            out.write(DataHelper.formatSize2(stats[5]) + "B, ");
    357378            out.write(ngettext("1 connected peer", "{0} connected peers", (int) stats[4]));
    358             out.write("\">");
    359             out.write(ngettext("1", "{0}", (int) stats[4]));
    360             out.write("</th>");
    361 //            out.write("&nbsp;&nbsp;");
    362 //            out.write(ngettext("1 torrent", "{0} torrents", snarks.size()));
    363             out.write("<th><img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_snarks.png\"");
    364             out.write(" title=\"");
    365             out.write(ngettext("1 torrent loaded", "{0} torrents loaded", snarks.size()));
    366             out.write("\">");
    367             out.write(ngettext("1", "{0}", snarks.size()));
    368             out.write("&nbsp;&nbsp;");
    369             out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_loaded.png\"");
    370             out.write(" title=\"");
    371             out.write(_("Total download size (pre-allocated): "));
    372             out.write(DataHelper.formatSize2(stats[5]) + "B");
    373             out.write("\">");
    374             out.write(DataHelper.formatSize2(stats[5]) + "B");
    375             out.write("</th>\n" +
    376                       "    <th>&nbsp;</th>\n" +
    377                       "    <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
     379            out.write("</th>\n");
     380            if (_manager.util().connected()) {
     381                out.write("    <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
    378382                      "    <th align=\"right\">" + formatSize(stats[1]) + "</th>\n" +
    379383                      "    <th align=\"right\">" + formatSize(stats[2]) + "ps</th>\n" +
    380384                      "    <th align=\"right\">" + formatSize(stats[3]) + "ps</th>\n" +
    381                       "    <th>&nbsp;</th></tr>\n" +
    382                       "</tfoot>\n");
     385                      "    <th></th>");
     386            } else {
     387                out.write("<th colspan=\"5\"></th>");
     388            }
     389            out.write("</tr></tfoot>\n");
    383390        }
    384391       
     
    394401        String action = req.getParameter("action");
    395402        if (action == null) {
    396             // noop
     403            _manager.addMessage("No action specified");
    397404            return;
    398405        }
    399         if (!"POST".equals(req.getMethod()))
    400             return;
     406        // sadly, Opera doesn't send value with input type=image, so we have to use GET there
     407        //if (!"POST".equals(req.getMethod())) {
     408        //    _manager.addMessage("Action must be with POST");
     409        //    return;
     410        //}
    401411        if ("Add".equals(action)) {
    402412            String newFile = req.getParameter("newFile");
    403413            String newURL = req.getParameter("newURL");
     414         /******
    404415            // NOTE - newFile currently disabled in HTML form - see below
    405416            File f = null;
     
    410421            }
    411422            if ( (f != null) && (f.exists()) ) {
     423                // NOTE - All this is disabled - load from local file disabled
    412424                File local = new File(_manager.getDataDir(), f.getName());
    413425                String canonical = null;
     
    432444                    _log.warn("hrm: " + local, ioe);
    433445                }
    434             } else if (newURL != null) {
     446            } else
     447          *****/
     448            if (newURL != null) {
    435449                if (newURL.startsWith("http://")) {
    436450                    _manager.addMessage(_("Fetching {0}", urlify(newURL)));
     
    617631                    snark.startTorrent();
    618632            }
     633        } else {
     634            _manager.addMessage("Unknown POST action: \"" + action + '\"');
    619635        }
    620636    }
     
    677693
    678694    private static final int MAX_DISPLAYED_FILENAME_LENGTH = 50;
    679     private static final int MAX_DISPLAYED_ERROR_LENGTH = 6;
    680     private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers, boolean showDebug) throws IOException {
     695    private static final int MAX_DISPLAYED_ERROR_LENGTH = 43;
     696    private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers,
     697                              boolean isDegraded, boolean showDebug) throws IOException {
    681698        String filename = snark.torrent;
    682699        File f = new File(filename);
     
    732749        }
    733750       
    734         String statusString = _("Unknown");
     751        String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
     752        String statusString;
    735753        if (err != null) {
    736754            if (isRunning && curPeers > 0 && !showPeers)
    737                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/trackererror.png\" title=\"" + _("Tracker Error") +
    738                                "\"><a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
    739                                ' ' + curPeers + "&thinsp;/&thinsp;" +
    740                                // ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    741                                ngettext("1", "{0}", knownPeers) + "</a>";
     755                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
     756                               ": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
     757                               curPeers + thinsp(isDegraded) +
     758                               ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    742759            else if (isRunning)
    743                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/trackererror.png\" title=\"" + _("Tracker Error") +
    744                                "\">" + ' ' + curPeers + "&thinsp;/&thinsp;" +
    745                                // ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    746                                ngettext("1", "{0}", knownPeers) + "</a>";
     760                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
     761                               ": " + curPeers + thinsp(isDegraded) +
     762                               ngettext("1 peer", "{0} peers", knownPeers);
    747763            else {
    748764                if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
    749765                    err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "&hellip;";
    750                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/trackererror.png\" title=\"" + _("Tracker Error") +
    751                 "\"> " + err + "</a>";
     766                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
     767                "<br>" + err;
    752768            }
    753769        } else if (remaining <= 0) {
    754770            if (isRunning && curPeers > 0 && !showPeers)
    755                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/seeding.png\" title=\"" + _("Seeding") + "\">" +
    756                                "<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
    757                                ' ' + curPeers + "&thinsp;/&thinsp;" +
    758                                // ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    759                                ngettext("1", "{0}", knownPeers) + "</a>";
     771                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
     772                               ": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
     773                               curPeers + thinsp(isDegraded) +
     774                               ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    760775            else if (isRunning)
    761                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/seeding.png\" title=\"" + _("Seeding") + "\">" +
    762                                ' ' + curPeers + "&thinsp;/&thinsp;" +
    763                                // ngettext("1 peer", "{0} peers", knownPeers)  + "</a>";
    764                                ngettext("1", "{0}", knownPeers)  + "</a>";
     776                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
     777                               ": " + curPeers + thinsp(isDegraded) +
     778                               ngettext("1 peer", "{0} peers", knownPeers);
    765779            else
    766                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/complete.png\" title=\"" + _("Complete") + "\"> " + _("Complete");
     780                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "complete.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Complete");
    767781        } else {
    768782            if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
    769                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/downloading.png\" title=\"" + _("Downloading") + "\">" +
    770                                "<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
    771                                ' ' + curPeers + "&thinsp;/&thinsp;" +
    772                              //  ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    773                                ngettext("1", "{0}", knownPeers) + "</a>";
     783                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
     784                               ": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
     785                               curPeers + thinsp(isDegraded) +
     786                               ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    774787            else if (isRunning && curPeers > 0 && downBps > 0)
    775                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/downloading.png\" title=\"" + _("Downloading") + "\">" +
    776                                ' ' + curPeers + "&thinsp;/&thinsp;" +
    777                                ngettext("1", "{0}", knownPeers);
    778                               //  ngettext("1 peer", "{0} peers", knownPeers);
     788                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
     789                               ": " + curPeers + thinsp(isDegraded) +
     790                               ngettext("1 peer", "{0} peers", knownPeers);
    779791            else if (isRunning && curPeers > 0 && !showPeers)
    780                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stalled.png\" title=\"" + _("Stalled") + "\">" +
    781                                "<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
    782                                ' ' + curPeers + "&thinsp;/&thinsp;" +
    783                                // ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    784                                ngettext("1", "{0}", knownPeers) + "</a>";                               
     792                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
     793                               ": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
     794                               curPeers + thinsp(isDegraded) +
     795                               ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    785796            else if (isRunning && curPeers > 0)
    786                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stalled.png\" title=\"" + _("Stalled") + "\">" +
    787                                ' ' + curPeers + "&thinsp;/&thinsp;" +
    788                                // ngettext("1 peer", "{0} peers", knownPeers);
    789                                ngettext("1", "{0}", knownPeers);
     797                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
     798                               ": " + curPeers + thinsp(isDegraded) +
     799                               ngettext("1 peer", "{0} peers", knownPeers);
     800            else if (isRunning && knownPeers > 0)
     801                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers") +
     802                               ": 0&thinsp;/&thinsp;" + knownPeers ;
    790803            else if (isRunning)
    791                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/nopeers.png\" title=\"" + _("No Peers") + "\">" +
    792                                ' ' + curPeers + "&thinsp;/&thinsp;" +
    793                                // ngettext("1 peer", "{0} peers", knownPeers);
    794                                ngettext("1", "{0}", knownPeers);
     804                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers");
    795805            else
    796                 statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stopped.png\" title=\"" + _("Stopped") + "\"> " + _("Stopped");
     806                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stopped.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stopped");
    797807        }
    798808       
    799         String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
    800809        out.write("<tr class=\"" + rowClass + "\">");
    801         out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">");
     810        out.write("<td class=\"center " + rowClass + "\">");
    802811        out.write(statusString + "</td>\n\t");
    803         out.write("<td align=\"left\" class=\"snarkTorrentName " + rowClass + "\">");
    804        
    805         if (remaining == 0 || snark.meta.getFiles() != null) {
    806             out.write("<a href=\"" + snark.storage.getBaseName());
    807             if (snark.meta.getFiles() != null)
    808                 out.write("/");
    809             out.write("\" title=\"");
    810             if (snark.meta.getFiles() != null)
    811                 out.write(_("View files"));
    812             else
    813                 out.write(_("Open file"));
    814             out.write("\">");
    815         }
    816         String icon;
    817         if (snark.meta.getFiles() != null)
    818             icon = "folder";
    819         else
    820             icon = toIcon(snark.meta.getName());
    821         out.write(toImg(icon));
    822         out.write(filename);
    823         if (remaining == 0 || snark.meta.getFiles() != null)
    824             out.write("</a>");
     812
     813        out.write("<td class=\"" + rowClass + "\">");
    825814        // temporarily hardcoded for postman* and anonymity, requires bytemonsoon patch for lookup by info_hash
    826815        String announce = snark.meta.getAnnounce();
     
    840829                    continue;
    841830                baseURL = baseURL.substring(e + 1);
    842                 out.write("&nbsp;<a href=\"" + baseURL + "details.php?dllist=1&filelist=1&info_hash=");
     831                out.write("<a href=\"" + baseURL + "details.php?dllist=1&amp;filelist=1&amp;info_hash=");
    843832                out.write(TrackerClient.urlencode(snark.meta.getInfoHash()));
    844                 out.write("\" title=\"" + name + ' ' + _("Tracker") + "\" target=\"_blank\">");
    845                 out.write("<div class=\"infoz\"><img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/details.png\"></div>");
     833                out.write("\" title=\"" + _("Details at {0} tracker", name) + "\" target=\"_blank\">");
     834                out.write("<img alt=\"" + _("Info") + "\" border=\"0\" src=\"" + _imgPath + "details.png\">");
    846835                out.write("</a>");
    847836                break;
    848837            }
    849838        }
    850         out.write("</td>\n\t");
    851        
    852         out.write("<td align=\"center\" class=\"snarkTorrentETA " + rowClass + "\">");
     839
     840        out.write("</td>\n<td class=\"" + rowClass + "\">");
     841        StringBuilder buf = null;
     842        if (remaining == 0 || snark.meta.getFiles() != null) {
     843            buf = new StringBuilder(128);
     844            buf.append("<a href=\"").append(snark.storage.getBaseName());
     845            if (snark.meta.getFiles() != null)
     846                buf.append('/');
     847            buf.append("\" title=\"");
     848            if (snark.meta.getFiles() != null)
     849                buf.append(_("View files"));
     850            else
     851                buf.append(_("Open file"));
     852            buf.append("\">");
     853            out.write(buf.toString());
     854        }
     855        String icon;
     856        if (snark.meta.getFiles() != null)
     857            icon = "folder";
     858        else
     859            icon = toIcon(snark.meta.getName());
     860        if (remaining == 0 || snark.meta.getFiles() != null) {
     861            out.write(toImg(icon, _("Open")));
     862            out.write("</a>");
     863        } else {
     864            out.write(toImg(icon));
     865        }
     866        out.write("</td><td class=\"snarkTorrentName " + rowClass + "\">");
     867        if (remaining == 0 || snark.meta.getFiles() != null)
     868            out.write(buf.toString());
     869        out.write(filename);
     870        if (remaining == 0 || snark.meta.getFiles() != null)
     871            out.write("</a>");
     872
     873        out.write("<td align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">");
    853874        if(isRunning && remainingSeconds > 0)
    854875            out.write(DataHelper.formatDuration2(remainingSeconds*1000)); // (eta 6h)
     
    856877        out.write("<td align=\"right\" class=\"snarkTorrentDownloaded " + rowClass + "\">");
    857878        if (remaining > 0)
    858             out.write(formatSize(total-remaining) + "/" + formatSize(total)); // 18MB/3GB; remove thin space so line does _not_ break. We don't want a break here.
     879            out.write(formatSize(total-remaining) + thinsp(isDegraded) + formatSize(total));
    859880        else
    860881            out.write(formatSize(total)); // 3GB
    861882        out.write("</td>\n\t");
    862         out.write("<td align=\"right\" class=\"snarkTorrentUploaded " + rowClass
    863                   + "\">" + formatSize(uploaded) + "</td>\n\t");
     883        out.write("<td align=\"right\" class=\"snarkTorrentUploaded " + rowClass + "\">");
     884        if(isRunning)
     885           out.write(formatSize(uploaded));
     886        out.write("</td>\n\t");
    864887        out.write("<td align=\"right\" class=\"snarkTorrentRateDown\">");
    865888        if(isRunning && remaining > 0)
     
    876899            parameters = parameters + "&p=1";
    877900        if (isRunning) {
    878             out.write("<input type=\"image\" name=\"action\" value=\"Stop_");
    879             out.write(b64);
    880             out.write("\" title=\"");
     901            if (isDegraded)
     902                out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
     903            else
     904                out.write("<input type=\"image\" name=\"action\" value=\"Stop_" + b64 + "\" title=\"");
    881905            out.write(_("Stop the torrent"));
    882             out.write("\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stop.png\" alt=\"");
     906            out.write("\" src=\"" + _imgPath + "stop.png\" alt=\"");
    883907            out.write(_("Stop"));
    884908            out.write("\">");
     909            if (isDegraded)
     910                out.write("</a>");
    885911        } else {
    886912            if (isValid) {
    887                 out.write("<input type=\"image\" name=\"action\" value=\"Start_");
    888                 out.write(b64);
    889                 out.write("\" title=\"");
     913                if (isDegraded)
     914                    out.write("<a href=\"/i2psnark/?action=Start_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
     915                else
     916                    out.write("<input type=\"image\" name=\"action\" value=\"Start_" + b64 + "\" title=\"");
    890917                out.write(_("Start the torrent"));
    891                 out.write("\" src=\"/themes/snark/" + _manager.getTheme() + "/images/start.png\" alt=\"");
     918                out.write("\" src=\"" + _imgPath + "start.png\" alt=\"");
    892919                out.write(_("Start"));
    893920                out.write("\">");
    894             }
    895 
    896             out.write("<input type=\"image\" name=\"action\" value=\"Remove_");
    897             out.write(b64);
    898             out.write("\" title=\"");
     921                if (isDegraded)
     922                    out.write("</a>");
     923            }
     924
     925            if (isDegraded)
     926                out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
     927            else
     928                out.write("<input type=\"image\" name=\"action\" value=\"Remove_" + b64 + "\" title=\"");
    899929            out.write(_("Remove the torrent from the active list, deleting the .torrent file"));
    900930            out.write("\" onclick=\"if (!confirm('");
     
    904934            out.write(_("Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?", fullFilename));
    905935            out.write("')) { return false; }\"");
    906             out.write(" src=\"/themes/snark/" + _manager.getTheme() + "/images/remove.png\" alt=\"");
     936            out.write(" src=\"" + _imgPath + "remove.png\" alt=\"");
    907937            out.write(_("Remove"));
    908938            out.write("\">");
    909 
    910             out.write("<input type=\"image\" name=\"action\" value=\"Delete_");
    911             out.write(b64);
    912             out.write("\" title=\"");
     939            if (isDegraded)
     940                out.write("</a>");
     941
     942            if (isDegraded)
     943                out.write("<a href=\"/i2psnark/?action=Delete_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
     944            else
     945                out.write("<input type=\"image\" name=\"action\" value=\"Delete_" + b64 + "\" title=\"");
    913946            out.write(_("Delete the .torrent file and the associated data file(s)"));
    914947            out.write("\" onclick=\"if (!confirm('");
     
    918951            out.write(_("Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?", fullFilename));
    919952            out.write("')) { return false; }\"");
    920             out.write(" src=\"/themes/snark/" + _manager.getTheme() + "/images/delete.png\" alt=\"");
     953            out.write(" src=\"" + _imgPath + "delete.png\" alt=\"");
    921954            out.write(_("Delete"));
    922955            out.write("\">");
     956            if (isDegraded)
     957                out.write("</a>");
    923958        }
    924959        out.write("</td>\n</tr>\n");
     
    931966                if (!peer.isConnected())
    932967                    continue;
    933                 out.write("<tr class=\"" + rowClass + "\">");
    934                 out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">");
    935                 out.write("</td>\n\t");
    936                 out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
     968                out.write("<tr class=\"" + rowClass + "\"><td></td>");
     969                out.write("<td colspan=\"4\" align=\"right\" class=\"" + rowClass + "\">");
    937970                String ch = peer.toString().substring(0, 4);
    938971                String client;
     
    10071040                out.write("</td></tr>\n\t");
    10081041                if (showDebug)
    1009                     out.write("<tr><td colspan=\"8\" align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">" + peer.getSocket() + "</td></tr>");
     1042                    out.write("<tr><td></td><td colspan=\"10\" align=\"right\" class=\"" + rowClass + "\">" + peer.getSocket() + "</td></tr>");
    10101043            }
    10111044        }
    10121045    }
    10131046   
     1047    /** @since 0.8.2 */
     1048    private static String thinsp(boolean disable) {
     1049        if (disable)
     1050            return " / ";
     1051        return ("&thinsp;/&thinsp;");
     1052    }
     1053
    10141054    /**
    10151055     *  Sort by completeness (seeds first), then by ID
     
    10351075        //if ( (newFile == null) || (newFile.trim().length() <= 0) ) newFile = "";
    10361076       
    1037         out.write("<span class=\"snarkNewTorrent\">\n");
     1077        out.write("<div class=\"snarkNewTorrent\">\n");
    10381078        // *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
    1039         out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
     1079        out.write("<form action=\"_post\" method=\"POST\">\n");
    10401080        out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
    10411081        out.write("<input type=\"hidden\" name=\"action\" value=\"Add\" >\n");
     
    10451085            out.write("<input type=\"hidden\" name=\"p\" value=\"" + peerParam + "\" >\n");
    10461086        out.write("<div class=\"addtorrentsection\"><span class=\"snarkConfigTitle\">");
    1047         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/add.png\">");
     1087        out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "add.png\"> ");
    10481088        out.write(_("Add Torrent"));
    10491089        out.write("</span><hr>\n<table border=\"0\"><tr><td>");
     
    10631103        out.write(_("Removing a .torrent will cause it to stop."));
    10641104        out.write("<br></span></table>\n");
    1065         out.write("</form>\n</span></div>"); 
     1105        out.write("</div></form></div>"); 
    10661106    }
    10671107   
     
    10741114            baseFile = DataHelper.stripHTML(baseFile);    // XSS
    10751115       
    1076         out.write("<div class=\"newtorrentsection\"><span class=\"snarkNewTorrent\">\n");
     1116        out.write("<div class=\"newtorrentsection\"><div class=\"snarkNewTorrent\">\n");
    10771117        // *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
    1078         out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
     1118        out.write("<form action=\"_post\" method=\"POST\">\n");
    10791119        out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
    10801120        out.write("<input type=\"hidden\" name=\"action\" value=\"Create\" >\n");
     
    10841124            out.write("<input type=\"hidden\" name=\"p\" value=\"" + peerParam + "\" >\n");
    10851125        out.write("<span class=\"snarkConfigTitle\">");
    1086         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/create.png\">");
     1126        out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "create.png\"> ");
    10871127        out.write(_("Create Torrent"));
    10881128        out.write("</span><hr>\n<table border=\"0\"><tr><td>");
     
    11171157        out.write(_("Create torrent"));
    11181158        out.write("\" name=\"foo\" ></table>\n");
    1119         out.write("</form>\n</span></div>");       
     1159        out.write("</form></div></div>");       
    11201160    }
    11211161   
     
    11281168        //int seedPct = 0;
    11291169       
    1130         out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
    1131         out.write("<div class=\"configsectionpanel\"><span class=\"snarkConfig\">\n");
     1170        out.write("<form action=\"/i2psnark/configure\" method=\"POST\">\n");
     1171        out.write("<div class=\"configsectionpanel\"><div class=\"snarkConfig\">\n");
    11321172        out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
    11331173        out.write("<input type=\"hidden\" name=\"action\" value=\"Save\" >\n");
    11341174        out.write("<span class=\"snarkConfigTitle\">");
    1135         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/config.png\">");
     1175        out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
    11361176        out.write(_("Configuration"));
    11371177        out.write("</span><hr>\n");
    11381178        out.write("<table border=\"0\"><tr><td>");
    11391179
    1140         out.write(_("Theme"));
    1141         out.write(": <td><select name='theme'>");
    1142         String theme = _manager.getTheme();
    1143         String[] themes = _manager.getThemes();
    1144         for(int i = 0; i < themes.length; i++) {
    1145             if(themes[i].equals(theme))
    1146                 out.write("\n<OPTION value='" + themes[i] + "' SELECTED>" + themes[i]);
    1147             else
    1148                 out.write("\n<OPTION value='" + themes[i] + "'>" + themes[i]);
    1149         }
    1150         out.write("\n</select>\n<tr><td>");
    1151 
    1152 
    11531180        out.write(_("Data directory"));
    1154         out.write(": <td><code>" + dataDir + "</code> (");
     1181        out.write(": <td><code>" + dataDir + "</code> <i>(");
    11551182        out.write(_("Edit i2psnark.config and restart to change"));
    11561183        out.write(")</i><br>\n");
     
    11631190        out.write(_("If checked, automatically start torrents that are added"));
    11641191        out.write("\" >");
     1192
     1193        out.write("<tr><td>");
     1194        out.write(_("Theme"));
     1195        out.write(": <td><select name='theme'>");
     1196        String theme = _manager.getTheme();
     1197        String[] themes = _manager.getThemes();
     1198        for(int i = 0; i < themes.length; i++) {
     1199            if(themes[i].equals(theme))
     1200                out.write("\n<OPTION value=\"" + themes[i] + "\" SELECTED>" + themes[i]);
     1201            else
     1202                out.write("\n<OPTION value=\"" + themes[i] + "\">" + themes[i]);
     1203        }
     1204        out.write("</select>\n");
    11651205
    11661206        out.write("<tr><td>");
     
    12641304        out.write(_("Save configuration"));
    12651305        out.write("\" name=\"foo\" >\n");
    1266         out.write("</table></span>\n");
    1267         out.write("</form></div>");
     1306        out.write("</table></div></div></form>");
    12681307    }
    12691308   
     
    12711310        out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n");
    12721311        out.write("<span class=\"snarkConfigTitle\"><a href=\"configure\">");
    1273         out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/config.png\">");
     1312        out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
    12741313        out.write(_("Configuration"));
    12751314        out.write("</a></span></span></div>\n");
     
    13471386    }
    13481387
    1349     private static final String HEADER_A = "<link href=\"/themes/snark/";
    1350     private static final String HEADER_B = "/snark.css\" rel=\"stylesheet\" type=\"text/css\" >";
    1351 
    1352 
    1353     private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\" cellpadding=\"0 10px\">\n" +
     1388    private static final String DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
     1389    private static final String HEADER_A = "<link href=\"";
     1390    private static final String HEADER_B = "snark.css\" rel=\"stylesheet\" type=\"text/css\" >";
     1391
     1392
     1393    private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\" >\n" +
    13541394                                               "<thead>\n" +
    1355                                                "<tr><th align=\"center\">";
    1356 
    1357     private static final String FOOTER = "</div></div></div></center></body></html>";
     1395                                               "<tr><th colspan=\"2\">";
     1396
     1397    private static final String FOOTER = "</div></center></body></html>";
    13581398
    13591399    /**
     
    13991439       
    14001440        StringBuilder buf=new StringBuilder(4096);
    1401         buf.append("<HTML><HEAD><TITLE>");
     1441        buf.append(DOCTYPE + "<HTML><HEAD><TITLE>");
    14021442        String title = URI.decodePath(base);
    14031443        if (title.startsWith("/i2psnark/"))
     
    14201460        title = _("Torrent") + ": " + title;
    14211461        buf.append(title);
    1422         buf.append("</TITLE>").append(HEADER_A).append(_manager.getTheme()).append(HEADER_B).append("<link rel=\"shortcut icon\" href=\"/themes/snark/" + _manager.getTheme() + "/favicon.ico\"></HEAD><BODY>\n<center><div class=\"snarknavbar\"> <a href=\"/i2psnark/\" title=\"Torrents\"");
    1423         buf.append(" class=\"snarkRefresh\"><img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/arrow_refresh.png\"> I2PSnark</a>").append("</div>");
     1462        buf.append("</TITLE>").append(HEADER_A).append(_themePath).append(HEADER_B).append("<link rel=\"shortcut icon\" href=\"" + _themePath + "favicon.ico\">" +
     1463             "</HEAD><BODY>\n<center><div class=\"snarknavbar\"><a href=\"/i2psnark/\" title=\"Torrents\"");
     1464        buf.append(" class=\"snarkRefresh\"><img alt=\"\" border=\"0\" src=\"" + _imgPath + "arrow_refresh.png\">&nbsp;&nbsp;I2PSnark</a></div></center>\n");
    14241465       
    1425         if (parent)
    1426             buf.append("</div><div class=\"page\"><div class=\"mainsection\">");
    1427             boolean showPriority = snark != null && !snark.storage.complete();
     1466        if (parent)  // always true
     1467            buf.append("<div class=\"page\"><div class=\"mainsection\">");
     1468        boolean showPriority = snark != null && !snark.storage.complete();
    14281469        if (showPriority)
    14291470            buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n");
    1430             buf.append("<TABLE BORDER=0 class=\"snarkTorrents\" cellpadding=\"5px 10px\">" +
     1471        buf.append("<TABLE BORDER=0 class=\"snarkTorrents\" >" +
    14311472            "<thead><tr><th>")
    1432             .append("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/file.png\" title=\"")
    1433             .append(_("File")).append("\" alt=\"").append(_("File")).append("\">&nbsp;")
     1473            .append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "file.png\" >&nbsp;")
    14341474            .append(title).append("</th><th align=\"right\">")
    1435             .append("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/size.png\" title=\"")
    1436 //            .append(_("FileSize")).append("\" alt=\"").append(_("FileSize")).append("\">").append(_("Size"));
    1437             .append(_("FileSize")).append("\" alt=\"").append(_("FileSize")).append("\">");
    1438             buf.append("</th><th class=\"headerstatus\">")
    1439             .append("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/status.png\" title=\"")
    1440 //            .append(_("Download Status")).append("\">").append(_("Status")).append("</th>");
    1441             .append(_("Download Status")).append("\">").append("</th>");
     1475            .append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "size.png\" >&nbsp;")
     1476            .append(_("Size"));
     1477        buf.append("</th><th class=\"headerstatus\">")
     1478            .append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "status.png\" >&nbsp;")
     1479            .append(_("Status")).append("</th>");
    14421480        if (showPriority)
    14431481            buf.append("<th class=\"headerpriority\">")
    1444             .append("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/priority.png\" title=\"")
    1445             .append(_("Priority")).append("\">").append("</th>");
    1446 //            .append(_("Priority")).append("</th>");
    1447 //            .append("</th>");
    1448             buf.append("</tr></thead>\n");
    1449             buf.append("<tr><td colspan=\"4\" class=\"ParentDir\"><A HREF=\"");
    1450             buf.append(URI.addPaths(base,"../"));
    1451             buf.append("\"><img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/up.png\"> ")
     1482            .append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "priority.png\" >&nbsp;")
     1483            .append(_("Priority")).append("</th>");
     1484        buf.append("</tr></thead>\n");
     1485        buf.append("<tr><td colspan=\"" + (showPriority ? '4' : '3') + "\" class=\"ParentDir\"><A HREF=\"");
     1486        buf.append(URI.addPaths(base,"../"));
     1487        buf.append("\"><img alt=\"\" border=\"0\" src=\"" + _imgPath + "up.png\"> ")
    14521488            .append(_("Up to higher level directory")).append("</A></td></tr>\n");
    14531489
     
    14751511            if (item.isDirectory()) {
    14761512                complete = true;
    1477                 status = toImg("tick") + _("Directory");
     1513                status = toImg("tick") + ' ' + _("Directory");
    14781514            } else {
    14791515                if (snark == null) {
    14801516                    // Assume complete, perhaps he removed a completed torrent but kept a bookmark
    14811517                    complete = true;
    1482                     status = toImg("cancel") + _("Torrent not found?");
     1518                    status = toImg("cancel") + ' ' + _("Torrent not found?");
    14831519                } else {
    14841520                    try {
     
    14881524                            if (remaining < 0) {
    14891525                                complete = true;
    1490                                 status = toImg("cancel") + _("File not found in torrent?");
     1526                                status = toImg("cancel") + ' ' + _("File not found in torrent?");
    14911527                            } else if (remaining == 0 || length <= 0) {
    14921528                                complete = true;
    1493                                 status = toImg("tick") + _("Complete");
     1529                                status = toImg("tick") + ' ' + _("Complete");
    14941530                            } else {
    14951531                                int priority = snark.storage.getPriority(f.getCanonicalPath());
     
    15001536                                else
    15011537                                    status = toImg("clock_red");
    1502                                 status +=
     1538                                status += " " +
    15031539                                         (100 * (length - remaining) / length) + "% " + _("complete") +
    15041540                                         " (" + DataHelper.formatSize2(remaining) + _("bytes remaining") + ")";
     
    15271563                       .append(path).append("\"></a> ");
    15281564                } else {
    1529                     buf.append(toImg(icon));
     1565                    buf.append(toImg(icon, _("Open"))).append("</a> ");
    15301566                }
    15311567                buf.append("<A HREF=\"");
     
    15331569                buf.append("\">");
    15341570            } else {
    1535                 buf.append(toImg(icon));
     1571                buf.append(toImg(icon)).append(' ');
    15361572            }
    15371573            buf.append(ls[i]);
     
    16411677    /** @since 0.7.14 */
    16421678    private static String toImg(String icon) {
    1643         return "<img alt=\"\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\"> ";
     1679        return "<img alt=\"\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\">";
     1680    }
     1681
     1682    /** @since 0.8.2 */
     1683    private static String toImg(String icon, String altText) {
     1684        return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\">";
    16441685    }
    16451686
     
    17031744                            _manager.addMessage(_("Torrent already in the queue: {0}", name));
    17041745                    } else {
    1705                         FileUtil.copy(file.getAbsolutePath(), canonical, true);
    1706                         _manager.addTorrent(canonical);
     1746                        boolean success = FileUtil.copy(file.getAbsolutePath(), canonical, false);
     1747                        if (success) {
     1748                            SecureFileOutputStream.setPerms(torrentFile);
     1749                            _manager.addTorrent(canonical);
     1750                        } else {
     1751                            _manager.addMessage(_("Failed to copy torrent file to {0}", canonical));
     1752                        }
    17071753                    }
    17081754                } catch (IOException ioe) {
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java

    rc3597cf rd4b0bfd  
    1616
    1717import net.i2p.client.streaming.I2PSocket;
     18import net.i2p.I2PAppContext;
    1819import net.i2p.data.DataHelper;
    1920import net.i2p.util.EventDispatcher;
     
    3738    private static final String DEST64_HEADER = "X-I2P-DestB64";
    3839    private static final String DEST32_HEADER = "X-I2P-DestB32";
     40    private static final String[] CLIENT_SKIPHEADERS = {HASH_HEADER, DEST64_HEADER, DEST32_HEADER};
     41    private static final String SERVER_HEADER = "Server";
     42    private static final String[] SERVER_SKIPHEADERS = {SERVER_HEADER};
    3943
    4044    public I2PTunnelHTTPServer(InetAddress host, int port, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
     
    7680
    7781            StringBuilder command = new StringBuilder(128);
    78             Properties headers = readHeaders(in, command);
     82            Properties headers = readHeaders(in, command,
     83                CLIENT_SKIPHEADERS, getTunnel().getContext());
    7984            headers.setProperty(HASH_HEADER, socket.getPeerDestination().calculateHash().toBase64());
    8085            headers.setProperty(DEST32_HEADER, Base32.encode(socket.getPeerDestination().calculateHash().getData()) + ".b32.i2p" );
     
    119124           
    120125            if (allowGZIP && useGZIP) {
    121                 I2PAppThread req = new I2PAppThread(new CompressedRequestor(s, socket, modifiedHeader), Thread.currentThread().getName()+".hc");
     126                I2PAppThread req = new I2PAppThread(
     127                    new CompressedRequestor(s, socket, modifiedHeader, getTunnel().getContext()),
     128                        Thread.currentThread().getName()+".hc");
    122129                req.start();
    123130            } else {
     
    156163        private I2PSocket _browser;
    157164        private String _headers;
    158         public CompressedRequestor(Socket webserver, I2PSocket browser, String headers) {
     165        private I2PAppContext _ctx;
     166        public CompressedRequestor(Socket webserver, I2PSocket browser, String headers, I2PAppContext ctx) {
    159167            _webserver = webserver;
    160168            _browser = browser;
    161169            _headers = headers;
     170            _ctx = ctx;
    162171        }
    163172        public void run() {
     
    201210                //Change headers to protect server identity
    202211                StringBuilder command = new StringBuilder(128);
    203                 Properties headers = readHeaders(serverin, command);
    204                 headers.setProperty("Server", "I2PServer");
     212                Properties headers = readHeaders(serverin, command,
     213                    SERVER_SKIPHEADERS, _ctx);
    205214                String modifiedHeaders = formatHeaders(headers, command);
    206215                compressedOut.write(modifiedHeaders.getBytes());
     
    337346    private static final int MAX_HEADERS = 60;
    338347
    339     private static Properties readHeaders(InputStream in, StringBuilder command) throws IOException {
     348    private static Properties readHeaders(InputStream in, StringBuilder command, String[] skipHeaders, I2PAppContext ctx) throws IOException {
    340349        Properties headers = new Properties();
    341350        StringBuilder buf = new StringBuilder(128);
     
    357366            }
    358367        }
    359         //if (trimmed > 0)
    360         //    getTunnel().getContext().statManager().addRateData("i2ptunnel.httpNullWorkaround", trimmed, 0);
     368        if (trimmed > 0)
     369            ctx.statManager().addRateData("i2ptunnel.httpNullWorkaround", trimmed, 0);
    361370       
    362371        int i = 0;
     
    380389                else
    381390                    value = "";
     391
    382392                if ("Accept-encoding".equalsIgnoreCase(name))
    383393                    name = "Accept-encoding";
    384394                else if ("X-Accept-encoding".equalsIgnoreCase(name))
    385395                    name = "X-Accept-encoding";
    386                 else if (HASH_HEADER.equalsIgnoreCase(name))
    387                     continue;     // Prevent spoofing
    388                 else if (DEST64_HEADER.equalsIgnoreCase(name))
    389                     continue;     // Prevent spoofing
    390                 else if (DEST32_HEADER.equalsIgnoreCase(name))
    391                     continue;     // Prevent spoofing
     396
     397                //We want to remove certain headers to improve anonymity
     398                boolean skip = false;
     399                for (String skipHeader: skipHeaders) {
     400                    if (skipHeader.equalsIgnoreCase(name)) {
     401                        skip = true;
     402                        break;
     403                    }
     404                }
     405                if(skip) {
     406                    continue;
     407                }
     408
    392409                headers.setProperty(name, value);
    393410                if (_log.shouldLog(Log.DEBUG))
  • build.xml

    rc3597cf rd4b0bfd  
    2424        <echo message="  installer: build the GUI installer" />
    2525        <echo message="  tarball:   tar the full install into i2p.tar.bz2 (extracts to build a new clean install)" />
    26         <echo message="  updater:   tar the built i2p specific files into an i2pupdate.zip (extracts safely over existing installs)" />
     26        <echo message="  updater:   Package the built files in i2pupdate.zip (extracts safely over existing installs)" />
     27        <echo message="  updater200: Updater compressed with pack200 (creates i2pupdate200.zip, 60% smaller)" />
    2728        <echo message="  updaterWithJavadoc: updater including the javadocs, for display in the console" />
    28         <echo message="  updaterWithJetty:   tar the built i2p specific files and jetty into an i2pupdate.zip (extracts safely over existing installs)" />
     29        <echo message="  updaterWithJetty: Updater including Jetty" />
    2930        <echo message="  updaterWithJettyFixes: updater including local jetty patches" />
    3031        <echo message="  updaterWithGeoIP: updater including GeoIP Files" />
     
    200201        <copy file="apps/addressbook/dist/addressbook.war" todir="build/" />
    201202    </target>
    202     <target name="poupdate">
     203    <!-- the apps need to compile the jsps to poupdate -->
     204    <target name="poupdate" depends="buildRouter, buildStreaming, buildSystray, buildJetty" >
    203205        <ant dir="apps/routerconsole/java/" target="poupdate" />
    204206        <ant dir="apps/i2psnark/java/" target="poupdate" />
  • core/java/src/net/i2p/client/I2PSessionDemultiplexer.java

    rc3597cf rd4b0bfd  
    3939        else {
    4040            // no listener, throw it out
    41             _log.error("No listener found for proto: " + proto + " port: " + toport + "msg id: " + msgId +
    42                        " from pool of " + _listeners.size() + " listeners");
     41            if (_listeners.isEmpty()) {
     42                if (_log.shouldLog(Log.WARN))
     43                    _log.warn("No listeners for incoming message");
     44            } else {
     45                _log.error("No listener found for proto: " + proto + " port: " + toport + " msg id: " + msgId +
     46                           " from pool of " + _listeners.size() + " listeners");
     47            }
    4348            try {
    4449                session.receiveMessage(msgId);
  • core/java/src/net/i2p/crypto/TrustedUpdate.java

    rc3597cf rd4b0bfd  
    177177     *  Duplicate keys or names rejected,
    178178     *  except that duplicate empty names are allowed
     179     *  @param key 172 character base64 string
     180     *  @param name non-null but "" ok
    179181     *  @since 0.7.12
    180182     *  @return true if successful
    181183     */
    182184    public boolean addKey(String key, String name) {
     185        String oldName = _trustedKeys.get(key);
     186        // already there?
     187        if (name.equals(oldName))
     188            return true;
     189        if (oldName != null && !oldName.equals("")) {
     190            _log.error("Key for " + name + " already stored for different name " + oldName + " : " + key);
     191            return false;
     192        }
    183193        SigningPublicKey signingPublicKey = new SigningPublicKey();
    184194        try {
    185             // fromBase64() won't reject a string that is too long
    186             if (key.length() != KEYSIZE_B64_BYTES)
    187                 throw new DataFormatException("x");
     195            // fromBase64() will throw a DFE if length is not right
    188196            signingPublicKey.fromBase64(key);
    189197        } catch (DataFormatException dfe) {
    190             _log.error("Bad signing key for " + name + " : " + key);
    191             return false;
    192         }
    193         if (_trustedKeys.containsKey(signingPublicKey) ||
    194             ((!name.equals("")) && _trustedKeys.containsValue(name))) {
    195             _log.error("Duplicate signing key for " + name + " : " + key);
     198            _log.error("Invalid signing key for " + name + " : " + key, dfe);
     199            return false;
     200        }
     201        if ((!name.equals("")) && _trustedKeys.containsValue(name)) {
     202            _log.error("Key mismatch for " + name + ", spoof attempt? : " + key);
    196203            return false;
    197204        }
  • core/java/src/net/i2p/util/LogRecordFormatter.java

    rc3597cf rd4b0bfd  
    3030
    3131    public static String formatRecord(LogManager manager, LogRecord rec) {
     32        return formatRecord(manager, rec, true);
     33    }
     34
     35    /**
     36     *  @param showDate if false, skip any date in the format (use when writing to wrapper log)
     37     *  @since 0.8.2
     38     */
     39    static String formatRecord(LogManager manager, LogRecord rec, boolean showDate) {
    3240        int size = 128 + rec.getMessage().length();
    3341        if (rec.getThrowable() != null)
     
    3846            switch (format[i]) {
    3947            case LogManager.DATE:
    40                 buf.append(getWhen(manager, rec));
     48                if (showDate)
     49                    buf.append(getWhen(manager, rec));
     50                else if (i+1 < format.length && format[i+1] == ' ')
     51                    i++;  // skip following space
    4152                break;
    4253            case LogManager.CLASS:
  • core/java/src/net/i2p/util/LogWriter.java

    rc3597cf rd4b0bfd  
    1717import java.io.Writer;
    1818import java.util.Queue;
    19 
    20 import net.i2p.I2PAppContext;
    2119
    2220/**
     
    113111
    114112    private void writeRecord(LogRecord rec) {
    115         String val = LogRecordFormatter.formatRecord(_manager, rec);
     113        String val = LogRecordFormatter.formatRecord(_manager, rec, true);
    116114        writeRecord(val);
    117115
     
    122120        if (_manager.getDisplayOnScreenLevel() <= rec.getPriority()) {
    123121            if (_manager.displayOnScreen()) {
    124                 System.out.print(val);
     122                // wrapper log already does time stamps, so reformat without the date
     123                if (System.getProperty("wrapper.version") != null)
     124                    System.out.print(LogRecordFormatter.formatRecord(_manager, rec, false));
     125                else
     126                    System.out.print(val);
    125127            }
    126128        }
     
    200202        File base = null;
    201203        if (!f.isAbsolute())
    202             base = I2PAppContext.getGlobalContext().getLogDir();
     204            base = _manager.getContext().getLogDir();
    203205
    204206        if ( (pattern.indexOf('#') < 0) && (pattern.indexOf('@') <= 0) ) {
  • history.txt

    rc3597cf rd4b0bfd  
     12010-12-11 zzz
     2    * Build: Fix 'ant distclean poupdate' again
     3    * I2CP: Change a log error to a warning (ticket #353)
     4    * i2psnark:
     5      - Restore text (ticket #273)
     6      - Fix several HTML errors (ticket #273)
     7      - Fix HTML error causing info links to be unclickable in dillo (tiicket #273)
     8      - Fix alt text duplicated or looking bad in text browsers (ticket #273)
     9      - Fix Opera button errors (ticket #332)
     10      - Fix POST resubmission errors (ticket #334)
     11      - Catch FetchAndAdd copy error (ticket #352)
     12      - Set permissions on downloaded torrent files
     13      - Hide some columns when not running
     14      - Lots of spacing cleanups
     15      - Rename images so users don't end up with unused files
     16      - Remove ~15 unused images
     17      - Clean up theme selection speed-coding exercise
     18      - Indent fixes
     19    * Log: Don't double-timestamp CRITS in wrapper.log
     20    * News: XML fixes (ticket #350)
     21    * Plugins: Better handling of signing keys (Ticket #351)
     22    * TunnelPoolManager: Fix rare startup NPE (http://forum.i2p/viewtopic.php?t=5192)
     23
     242010-12-10 Mathiasdm
     25    * I2PTunnel: Fixed up security fix.
     26
    1272010-12-07 Mathiasdm
    228    * I2PTunnel: Security fix: change server reply
  • installer/resources/checklist.txt

    rc3597cf rd4b0bfd  
    99Change revision in:
    1010        history.txt
    11         installer/resources/initialNews.xml
    1211        installer/install.xml
    1312        installer/resources/news.xml
     
    2221Verify that no untrusted revisions were inadvertently
    2322blessed by a trusted party:
    24         mtn log --brief --no-graph --to t:i2p-0.7.(xx-1) | cut -d ' ' -f 2- | sort
     23        mtn log --brief --no-graph --to t:i2p-0.8.(xx-1) | cut -d ' ' -f 2 | sort | uniq -c
    2524
    2625NOTE: Most tasks below here are now automated by 'ant release'
  • installer/resources/initialNews/initialNews.xml

    rc3597cf rd4b0bfd  
    11<div lang="en">
    2 <h4><ul><li>Congratulations on getting I2P installed!</li></ul></h4>
     2<h3>Congratulations on getting I2P installed!</h3>
    33<p>
    44<b>Welcome to I2P!</b>
  • installer/resources/initialNews/initialNews_de.xml

    rc3597cf rd4b0bfd  
    11<div lang="de">
    2 <h4><ul><li>Wir gratulieren zur erfolgreichen Installation von I2P!</li></ul></h4>
     2<h3>Wir gratulieren zur erfolgreichen Installation von I2P!</h3>
    33<p>
    44<b>Willkommen im I2P!</b>
  • installer/resources/initialNews/initialNews_es.xml

    rc3597cf rd4b0bfd  
    11<div lang="es">
    2 <h4><ul><li>&iexcl;Felicidades!, has instalado el enrutador I2P con &eacute;xito.</li></ul></h4>
     2<h3>&iexcl;Felicidades!, has instalado el enrutador I2P con &eacute;xito.</h3>
    33<p>
    44<b>&iexcl;Bienvenido a I2P!</b><br>
  • installer/resources/initialNews/initialNews_nl.xml

    rc3597cf rd4b0bfd  
    11<div lang="nl">
    2 <h4><ul><li>Gefeliciteerd met de installatie van I2P!</li></ul></h4>
     2<h3>Gefeliciteerd met de installatie van I2P!</h3>
    33<p>
    44<b>Welkom bij I2P!</b>
  • installer/resources/initialNews/initialNews_pt.xml

    rc3597cf rd4b0bfd  
    11<div lang="pt">
    2 <h4><ul><li>Parabéns, você instalou o roteador I2P com êxito!</li></ul></h4>
     2<h3>Parabéns, você instalou o roteador I2P com êxito!</h3>
    33<p>
    44<b>Bem-vindo ao I2P!</b><br>
  • installer/resources/initialNews/initialNews_ru.xml

    rc3597cf rd4b0bfd  
    11<div lang="ru">
    2 <h4><ul><li>Поздравляем с успешным завершением установки I2P!</li></ul></h4>
     2<h3>Поздравляем с успешным завершением установки I2P!</h3>
    33<p>
    44<b>Добро пожаловать в I2P!</b> Немного терпения! I2P-маршрутизатору потребуется пара минут для запуска модулей и первого подключения к сети I2P.
  • installer/resources/news.xml

    rc3597cf rd4b0bfd  
    44-->
    55<div lang="en">
    6 <h4><ul><li>2010-11-15: <b>0.8.1 <a href="http://www.i2p2.i2p/release-0.8.1.html">Released</a></b></li></ul></h4>
     6<h3>2010-11-15: <b>0.8.1 <a href="http://www.i2p2.i2p/release-0.8.1.html">Released</a></b></h3>
    77<p>
    88The 0.8.1 release contains the usual collection of bug fixes,
  • installer/resources/themes/snark/ubergine/snark.css

    rc3597cf rd4b0bfd  
    156156     color: #ddd;
    157157     whitespace: nowrap;
    158      font-variant: small-caps !important;
    159158     letter-spacing: 0.05em;
    160159}
     
    239238}
    240239
     240.center {
     241     text-align: center !important;
     242}
     243
    241244.snarkTorrentName {
    242245     text-shadow:1px 1px #550000;
     
    269272
    270273.snarkTorrentEven {
    271      background: #545;
    272274     font-size: 8pt;
    273275     background: #202;
     
    324326
    325327.snarkTorrentOdd {
    326      background: #656;
    327328     background: #351933;
    328329     font-size: 8pt;
  • installer/resources/themes/snark/vanilla/snark.css

    rc3597cf rd4b0bfd  
    140140
    141141thead, tfoot {
    142      text-shadow: 0px 1px 1px #707;
    143142     background: url("images/bling2.png") repeat-x scroll center center #867;
    144143     font-weight: bold;
     
    162161     border-bottom: 1px inset #604;
    163162     whitespace: nowrap;
    164      font-variant: small-caps !important;
    165163     letter-spacing: 0.05em;
    166164}
     
    245243}
    246244
     245.center {
     246     text-align: center !important;
     247}
     248
    247249.snarkTorrentName {
    248250/*     text-shadow:1px 1px #540;*/
     
    271273
    272274.snarkTorrentEven {
    273      background: #fef;
    274275     font-size: 8pt;
    275276     background: #feb;
     
    329330
    330331.snarkTorrentOdd {
    331      background: #656;
    332332     background: #fed;
    333333     font-size: 8pt;
     
    491491input.r {
    492492     text-align: right;
    493      background: /*url('/themes/snark/ubergine/images/graytile.png')*/;
    494493}
    495494
     
    525524     border: medium none;
    526525     margin: 0 2px;
    527      opacity: 0.9 !important;
     526     opacity: 0.8 !important;
    528527}
    529528
     
    562561
    563562textarea {
    564      background: #fff; /*/*url('/themes/snark/ubergine/images/graytile.png')*/;*/
     563     background: #fff; /*url('/themes/snark/ubergine/images/graytile.png');*/
    565564     color: #f60;
    566565     font-weight: bold;
  • router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java

    rc3597cf rd4b0bfd  
    132132                    return info;
    133133        }
    134         info = _inboundExploratory.getTunnel(id);
    135         if (info != null) return info;
    136         info = _outboundExploratory.getTunnel(id);
    137         if (info != null) return info;
     134        if (_inboundExploratory != null) {
     135            info = _inboundExploratory.getTunnel(id);
     136            if (info != null) return info;
     137        }
     138        if (_outboundExploratory != null) {
     139            info = _outboundExploratory.getTunnel(id);
     140            if (info != null) return info;
     141        }
    138142        return null;
    139143    }
Note: See TracChangeset for help on using the changeset viewer.