Changeset 81975e9


Ignore:
Timestamp:
Dec 22, 2012 6:34:51 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
470b8c5
Parents:
9a241af (diff), 436d8f0 (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:

propagate from branch 'i2p.i2p.zzz.test2' (head f33dbe1499b84cf6192b1a7bd494eaf081a047c0)

to branch 'i2p.i2p' (head 4e5bd2836592b95e1eff01d8e83f2690da386ef8)

Files:
16 edited

Legend:

Unmodified
Added
Removed
  • LICENSE.txt

    r9a241af r81975e9  
    239239      See licenses/LICENSE-LGPLv2.1.txt
    240240
    241    Tomcat 6.0.35:
    242    Copyright 1999-2011 The Apache Software Foundation
     241   Tomcat 6.0.36:
     242   Copyright 1999-2012 The Apache Software Foundation
    243243   See licenses/LICENSE-Apache2.0.txt
    244244   See licenses/NOTICE-Tomcat.txt
  • apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java

    r9a241af r81975e9  
    6262  private final long length;
    6363  private final boolean privateTorrent;
     64  private final List<List<String>> announce_list;
    6465  private Map<String, BEValue> infoMap;
    6566
     
    7071   *  @param files null for single-file torrent
    7172   *  @param lengths null for single-file torrent
     73   *  @param announce_list may be null
    7274   */
    7375  MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
    74            int piece_length, byte[] piece_hashes, long length, boolean privateTorrent)
     76           int piece_length, byte[] piece_hashes, long length, boolean privateTorrent,
     77           List<List<String>> announce_list)
    7578  {
    7679    this.announce = announce;
     
    8487    this.length = length;
    8588    this.privateTorrent = privateTorrent;
     89    this.announce_list = announce_list;
    8690
    8791    // TODO if we add a parameter for other keys
     
    140144    } else {
    141145        this.announce = val.getString();
     146    }
     147
     148    // BEP 12
     149    val = m.get("announce-list");
     150    if (val == null) {
     151        this.announce_list = null;
     152    } else {
     153        this.announce_list = new ArrayList();
     154        List<BEValue> bl1 = val.getList();
     155        for (BEValue bev : bl1) {
     156            List<BEValue> bl2 = bev.getList();
     157            List<String> sl2 = new ArrayList();           
     158            for (BEValue bev2 : bl2) {
     159                sl2.add(bev2.getString());
     160            }
     161            this.announce_list.add(sl2);
     162        }
    142163    }
    143164
     
    298319
    299320  /**
     321   * Returns a list of lists of urls.
     322   *
     323   * @since 0.9.5
     324   */
     325  public List<List<String>> getAnnounceList() {
     326    return announce_list;
     327  }
     328
     329  /**
    300330   * Returns the original 20 byte SHA1 hash over the bencoded info map.
    301331   */
     
    471501   * Creates a copy of this MetaInfo that shares everything except the
    472502   * announce URL.
     503   * Drops any announce-list.
    473504   */
    474505  public MetaInfo reannounce(String announce)
     
    476507    return new MetaInfo(announce, name, name_utf8, files,
    477508                        lengths, piece_length,
    478                         piece_hashes, length, privateTorrent);
     509                        piece_hashes, length, privateTorrent, null);
    479510  }
    480511
     
    487518        if (announce != null)
    488519            m.put("announce", announce);
     520        if (announce_list != null)
     521            m.put("announce-list", announce_list);
    489522        Map info = createInfoMap();
    490523        m.put("info", info);
  • apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java

    r9a241af r81975e9  
    887887                    }
    888888                } catch (IOException ioe) {
    889                     addMessage(_("Torrent in \"{0}\" is invalid", sfile.getName()) + ": " + ioe.getMessage());
     889                    String err = _("Torrent in \"{0}\" is invalid", sfile.getName()) + ": " + ioe.getMessage();
     890                    addMessage(err);
     891                    _log.error(err, ioe);
    890892                    if (sfile.exists())
    891893                        sfile.delete();
  • apps/i2psnark/java/src/org/klomp/snark/Storage.java

    r9a241af r81975e9  
    123123   */
    124124  public Storage(I2PSnarkUtil util, File baseFile, String announce,
     125                 List<List<String>> announce_list,
    125126                 boolean privateTorrent, StorageListener listener)
    126127    throws IOException
     
    183184    byte[] piece_hashes = fast_digestCreate();
    184185    metainfo = new MetaInfo(announce, baseFile.getName(), null, files,
    185                             lengthsList, piece_size, piece_hashes, total, privateTorrent);
     186                            lengthsList, piece_size, piece_hashes, total, privateTorrent,
     187                            announce_list);
    186188
    187189  }
     
    12261228      FileOutputStream out = null;
    12271229      try {
    1228           Storage storage = new Storage(util, base, announce, false, null);
     1230          Storage storage = new Storage(util, base, announce, null, false, null);
    12291231          MetaInfo meta = storage.getMetaInfo();
    12301232          file = new File(storage.getBaseName() + ".torrent");
  • apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java

    r9a241af r81975e9  
    3232import java.util.Collections;
    3333import java.util.Date;
     34import java.util.HashSet;
    3435import java.util.Iterator;
    3536import java.util.List;
     
    4142import net.i2p.data.DataHelper;
    4243import net.i2p.data.Hash;
     44import net.i2p.util.ConvertToHash;
    4345import net.i2p.util.I2PAppThread;
    4446import net.i2p.util.Log;
     
    110112  private volatile boolean _fastUnannounce;
    111113  private long lastDHTAnnounce;
    112   private final List<Tracker> trackers;
    113   private final List<Tracker> backupTrackers;
     114  private final List<TCTracker> trackers;
     115  private final List<TCTracker> backupTrackers;
    114116
    115117  /**
     
    271273    else if (additionalTrackerURL != null)
    272274        primary = additionalTrackerURL;
     275    Set<Hash> trackerHashes = new HashSet(8);
     276
     277    // primary tracker
    273278    if (primary != null) {
    274         if (isValidAnnounce(primary)) {
    275             trackers.add(new Tracker(primary, true));
     279        if (isNewValidTracker(trackerHashes, primary)) {
     280            trackers.add(new TCTracker(primary, true));
    276281            if (_log.shouldLog(Log.DEBUG))
    277282                _log.debug("Announce: [" + primary + "] infoHash: " + infoHash);
     
    282287    } else {
    283288        _log.warn("No primary announce");
    284         primary = "";
    285     }
     289    }
     290
     291    // announce list
     292    if (meta != null && !meta.isPrivate()) {
     293        List<List<String>> list = meta.getAnnounceList();
     294        if (list != null) {
     295            for (List<String> llist : list) {
     296                for (String url : llist) {
     297                    if (!isNewValidTracker(trackerHashes, url))
     298                        continue;
     299                    trackers.add(new TCTracker(url, trackers.isEmpty()));
     300                    if (_log.shouldLog(Log.DEBUG))
     301                        _log.debug("Additional announce (list): [" + url + "] for infoHash: " + infoHash);
     302                }
     303            }
     304        }
     305    }
     306
     307    // configured open trackers
    286308    if (meta == null || !meta.isPrivate()) {
    287309        List<String> tlist = _util.getOpenTrackers();
    288310        for (int i = 0; i < tlist.size(); i++) {
    289              String url = tlist.get(i);
    290              if (!isValidAnnounce(url)) {
    291                 _log.error("Bad announce URL: [" + url + "]");
     311            String url = tlist.get(i);
     312            if (!isNewValidTracker(trackerHashes, url))
    292313                continue;
    293              }
    294              int slash = url.indexOf('/', 7);
    295              if (slash <= 7) {
    296                 _log.error("Bad announce URL: [" + url + "]");
    297                 continue;
    298              }
    299              if (primary.startsWith(url.substring(0, slash)))
    300                 continue;
    301              String dest = _util.lookup(url.substring(7, slash));
    302              if (dest == null) {
    303                 _log.error("Announce host unknown: [" + url.substring(7, slash) + "]");
    304                 continue;
    305              }
    306              if (primary.startsWith("http://" + dest))
    307                 continue;
    308              if (primary.startsWith("http://i2p/" + dest))
    309                 continue;
    310              // opentrackers are primary if we don't have primary
    311              trackers.add(new Tracker(url, primary.equals("")));
    312              if (_log.shouldLog(Log.DEBUG))
    313                  _log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
     314            // opentrackers are primary if we don't have primary
     315            trackers.add(new TCTracker(url, trackers.isEmpty()));
     316            if (_log.shouldLog(Log.DEBUG))
     317                _log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
    314318        }
    315319    }
     
    319323        List<String> tlist = _util.getBackupTrackers();
    320324        for (int i = 0; i < tlist.size(); i++) {
    321              String url = tlist.get(i);
    322              if (!isValidAnnounce(url)) {
    323                 _log.error("Bad announce URL: [" + url + "]");
     325            String url = tlist.get(i);
     326            if (!isNewValidTracker(trackerHashes, url))
    324327                continue;
    325              }
    326              int slash = url.indexOf('/', 7);
    327              if (slash <= 7) {
    328                 _log.error("Bad announce URL: [" + url + "]");
    329                 continue;
    330              }
    331              String dest = _util.lookup(url.substring(7, slash));
    332              if (dest == null) {
    333                 _log.error("Announce host unknown: [" + url.substring(7, slash) + "]");
    334                 continue;
    335              }
    336              backupTrackers.add(new Tracker(url, false));
    337              if (_log.shouldLog(Log.DEBUG))
    338                  _log.debug("Backup announce: [" + url + "] for infoHash: " + infoHash);
     328            backupTrackers.add(new TCTracker(url, false));
     329            if (_log.shouldLog(Log.DEBUG))
     330                _log.debug("Backup announce: [" + url + "] for infoHash: " + infoHash);
    339331        }
    340         if (backupTrackers.isEmpty())
    341             backupTrackers.add(new Tracker(DEFAULT_BACKUP_TRACKER, false));
     332        if (backupTrackers.isEmpty()) {
     333            backupTrackers.add(new TCTracker(DEFAULT_BACKUP_TRACKER, false));
     334        }
    342335    }
    343336    this.completed = coordinator.getLeft() == 0;
     337  }
     338
     339  /**
     340   *  @param existing the ones we already know about
     341   *  @param ann an announce URL non-null
     342   *  @return true if ann is valid and new; adds to existing if returns true
     343   *  @since 0.9.5
     344   */
     345  private boolean isNewValidTracker(Set<Hash> existing, String ann) {
     346      Hash h = getHostHash(ann);
     347      if (h == null) {
     348         _log.error("Bad announce URL: [" + ann + ']');
     349         return false;
     350      }
     351      boolean rv = existing.add(h);
     352      if (!rv) {
     353          if (_log.shouldLog(Log.INFO))
     354             _log.info("Dup announce URL: [" + ann + ']');
     355      }
     356      return rv;
    344357  }
    345358
     
    426439   *  @return max peers seen
    427440   */
    428   private int getPeersFromTrackers(List<Tracker> trckrs) {
     441  private int getPeersFromTrackers(List<TCTracker> trckrs) {
    429442            long uploaded = coordinator.getUploaded();
    430443            long downloaded = coordinator.getDownloaded();
     
    443456            // *** loop once for each tracker
    444457            int maxSeenPeers = 0;
    445             for (Tracker tr : trckrs) {
     458            for (TCTracker tr : trckrs) {
    446459              if ((!stop) && (!tr.stop) &&
    447460                  (completed || coordinator.needOutboundPeers() || !tr.started) &&
     
    640653          dht.unannounce(snark.getInfoHash());
    641654      int i = 0;
    642       for (Tracker tr : trackers) {
     655      for (TCTracker tr : trackers) {
    643656          if (_util.connected() &&
    644657              tr.started && (!tr.stop) && tr.trackerProblems == null) {
     
    660673   */
    661674  private class Unannouncer implements Runnable {
    662      private final Tracker tr;
    663 
    664      public Unannouncer(Tracker tr) {
     675     private final TCTracker tr;
     676
     677     public Unannouncer(TCTracker tr) {
    665678         this.tr = tr;
    666679     }
     
    686699  }
    687700 
    688   private TrackerInfo doRequest(Tracker tr, String infoHash,
     701  private TrackerInfo doRequest(TCTracker tr, String infoHash,
    689702                                String peerID, long uploaded,
    690703                                long downloaded, long left, String event)
     
    776789
    777790  /**
     791   *  @param ann an announce URL
    778792   *  @return true for i2p hosts only
    779793   *  @since 0.7.12
     
    791805  }
    792806
    793   private static class Tracker
     807  /**
     808   *  @param ann an announce URL non-null
     809   *  @return a Hash for i2p hosts only, null otherwise
     810   *  @since 0.9.5
     811   */
     812  private static Hash getHostHash(String ann) {
     813    URL url;
     814    try {
     815        url = new URL(ann);
     816    } catch (MalformedURLException mue) {
     817        return null;
     818    }
     819    if (url.getPort() >= 0 || !url.getProtocol().equals("http"))
     820        return null;
     821    String host = url.getHost();
     822    if (host.endsWith(".i2p"))
     823        return ConvertToHash.getHash(host);
     824    if (host.equals("i2p")) {
     825        String path = url.getPath();
     826        if (path == null || path.length() < 517 ||
     827            !path.startsWith("/"))
     828            return null;
     829        String[] parts = path.substring(1).split("/?&;", 2);
     830        return ConvertToHash.getHash(parts[0]);
     831    }
     832    return null;
     833  }
     834
     835  private static class TCTracker
    794836  {
    795       String announce;
    796       boolean isPrimary;
     837      final String announce;
     838      final boolean isPrimary;
    797839      long interval;
    798840      long lastRequestTime;
     
    804846      int seenPeers;
    805847
    806       public Tracker(String a, boolean p)
     848      public TCTracker(String a, boolean p)
    807849      {
    808850          announce = a;
  • apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java

    r9a241af r81975e9  
    6262    private String _themePath;
    6363    private String _imgPath;
    64     private String _lastAnnounceURL = "";
     64    private String _lastAnnounceURL;
    6565   
    6666    public static final String PROP_CONFIG_FILE = "i2psnark.configFile";
     
    731731                //    announceURL = announceURLOther;
    732732
    733                 if (announceURL == null || announceURL.length() <= 0)
    734                     _manager.addMessage(_("Error creating torrent - you must select a tracker"));
    735                 else if (baseFile.exists()) {
    736                     _lastAnnounceURL = announceURL;
     733                if (baseFile.exists()) {
    737734                    if (announceURL.equals("none"))
    738735                        announceURL = null;
     736                    _lastAnnounceURL = announceURL;
     737                    List<String> backupURLs = new ArrayList();
     738                    Enumeration e = req.getParameterNames();
     739                    while (e.hasMoreElements()) {
     740                         Object o = e.nextElement();
     741                         if (!(o instanceof String))
     742                             continue;
     743                         String k = (String) o;
     744                        if (k.startsWith("backup_")) {
     745                            String url = k.substring(7);
     746                            if (!url.equals(announceURL))
     747                                backupURLs.add(url);
     748                        }
     749                    }
     750                    List<List<String>> announceList = null;
     751                    if (!backupURLs.isEmpty()) {
     752                        // BEP 12 - Put primary first, then the others, each as the sole entry in their own list
     753                        if (announceURL == null) {
     754                            _manager.addMessage(_("Error - Cannot include alternate trackers without a primary tracker"));
     755                            return;
     756                        }
     757                        backupURLs.add(0, announceURL);
     758                        boolean hasPrivate = false;
     759                        boolean hasPublic = false;
     760                        for (String url : backupURLs) {
     761                            if (_manager.getPrivateTrackers().contains(announceURL))
     762                                hasPrivate = true;
     763                            else
     764                                hasPublic = true;
     765                        }
     766                        if (hasPrivate && hasPublic) {
     767                            _manager.addMessage(_("Error - Cannot mix private and public trackers in a torrent"));
     768                            return;
     769                        }
     770                        announceList = new ArrayList(backupURLs.size());
     771                        for (String url : backupURLs) {
     772                            announceList.add(Collections.singletonList(url));
     773                        }
     774                    }
    739775                    try {
    740776                        // This may take a long time to check the storage, but since it already exists,
     
    742778                        // TODO thread it for big torrents, perhaps a la FetchAndAdd
    743779                        boolean isPrivate = _manager.getPrivateTrackers().contains(announceURL);
    744                         Storage s = new Storage(_manager.util(), baseFile, announceURL, isPrivate, null);
     780                        Storage s = new Storage(_manager.util(), baseFile, announceURL, announceList, isPrivate, null);
    745781                        s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
    746782                        MetaInfo info = s.getMetaInfo();
     
    13731409
    13741410    /**
     1411     *  Start of anchor only, caller must add anchor text or img and close anchor
    13751412     *  @return string or null
    13761413     *  @since 0.8.4
     
    14001437
    14011438    /**
     1439     *  Full anchor with img
    14021440     *  @return string or null
    14031441     *  @since 0.8.4
     
    14131451        }
    14141452        return null;
     1453    }
     1454
     1455    /**
     1456     *  Full anchor with shortened URL as anchor text
     1457     *  @return string, non-null
     1458     *  @since 0.9.5
     1459     */
     1460    private String getShortTrackerLink(String announce, byte[] infohash) {
     1461        StringBuilder buf = new StringBuilder(128);
     1462        String trackerLinkUrl = getTrackerLinkUrl(announce, infohash);
     1463        if (trackerLinkUrl != null)
     1464            buf.append(trackerLinkUrl);
     1465        if (announce.startsWith("http://"))
     1466            announce = announce.substring(7);
     1467        int slsh = announce.indexOf('/');
     1468        if (slsh > 0)
     1469            announce = announce.substring(0, slsh);
     1470        if (announce.length() > 67)
     1471            announce = announce.substring(0, 40) + "&hellip;" + announce.substring(announce.length() - 8);
     1472        buf.append(announce);
     1473        if (trackerLinkUrl != null)
     1474            buf.append("</a>");
     1475        return buf.toString();
    14151476    }
    14161477
     
    14831544        out.write(_("File or directory to seed (must be within the specified path)"));
    14841545        out.write("\" ><tr><td>\n");
    1485         out.write(_("Tracker"));
    1486         out.write(":<td><select name=\"announceURL\"><option value=\"\">");
    1487         out.write(_("Select a tracker"));
    1488         out.write("</option>\n");
    1489         // todo remember this one with _lastAnnounceURL also
    1490         out.write("<option value=\"none\">");
    1491         //out.write(_("Open trackers and DHT only"));
    1492         out.write(_("Open trackers only"));
    1493         out.write("</option>\n");
     1546        out.write(_("Trackers"));
     1547        out.write(":<td><table style=\"width: 20%;\"><tr><td></td><td align=\"center\">");
     1548        out.write(_("Primary"));
     1549        out.write("</td><td align=\"center\">");
     1550        out.write(_("Alternates"));
     1551        out.write("</td></tr>\n");
    14941552        for (Tracker t : sortedTrackers) {
    14951553            String name = t.name;
    14961554            String announceURL = t.announceURL.replace("&#61;", "=");
     1555            out.write("<tr><td>");
     1556            out.write(name);
     1557            out.write("</td><td align=\"center\"><input type=\"radio\" name=\"announceURL\" value=\"");
     1558            out.write(announceURL);
     1559            out.write("\"");
    14971560            if (announceURL.equals(_lastAnnounceURL))
    1498                 announceURL += "\" selected=\"selected";
    1499             out.write("\t<option value=\"" + announceURL + "\">" + name + "</option>\n");
    1500         }
    1501         out.write("</select>\n");
     1561                out.write(" checked");
     1562            out.write("></td><td align=\"center\"><input type=\"checkbox\" name=\"backup_");
     1563            out.write(announceURL);
     1564            out.write("\" value=\"foo\"></td></tr>\n");
     1565        }
     1566        out.write("<tr><td>");
     1567        out.write(_("none"));
     1568        out.write("</td><td align=\"center\"><input type=\"radio\" name=\"announceURL\" value=\"none\"");
     1569        if (_lastAnnounceURL == null)
     1570            out.write(" checked");
     1571        out.write("></td><td></td></tr></table>\n");
    15021572        // make the user add a tracker on the config form now
    15031573        //out.write(_("or"));
     
    19992069                    if (trackerLink != null)
    20002070                        buf.append(trackerLink).append(' ');
    2001                     buf.append("<b>").append(_("Tracker")).append(":</b> ");
    2002                     String trackerLinkUrl = getTrackerLinkUrl(announce, snark.getInfoHash());
    2003                     if (trackerLinkUrl != null)
    2004                         buf.append(trackerLinkUrl);
    2005                     if (announce.startsWith("http://"))
    2006                         announce = announce.substring(7);
    2007                     int slsh = announce.indexOf('/');
    2008                     if (slsh > 0)
    2009                         announce = announce.substring(0, slsh);
    2010                     if (announce.length() > 67)
    2011                         announce = announce.substring(0, 40) + "&hellip;" + announce.substring(announce.length() - 8);
    2012                     buf.append(announce);
    2013                     if (trackerLinkUrl != null)
    2014                         buf.append("</a>");
     2071                    buf.append("<b>").append(_("Primary Tracker")).append(":</b> ");
     2072                    buf.append(getShortTrackerLink(announce, snark.getInfoHash()));
     2073                    buf.append("</td></tr>");
     2074                }
     2075                List<List<String>> alist = meta.getAnnounceList();
     2076                if (alist != null) {
     2077                    buf.append("<tr><td><b>");
     2078                    buf.append(_("Tracker List")).append(":</b> ");
     2079                    for (List<String> alist2 : alist) {
     2080                        buf.append('[');
     2081                        boolean more = false;
     2082                        for (String s : alist2) {
     2083                            if (more)
     2084                                buf.append(' ');
     2085                            else
     2086                                more = true;
     2087                            buf.append(getShortTrackerLink(s, snark.getInfoHash()));
     2088                        }
     2089                        buf.append("] ");
     2090                    }
    20152091                    buf.append("</td></tr>");
    20162092                }
  • apps/i2ptunnel/jsp/editClient.jsp

    r9a241af r81975e9  
    249249                    <option value="3"<%=(tunnelQuantity == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)")%></option>
    250250                <% if (tunnelQuantity > 3) {
    251                 %>    <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> <%=intl._("tunnels")%></option>
     251                %>    <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%>&nbsp;<%=intl._("tunnels")%></option>
    252252                <% }
    253253              %></select>               
  • apps/i2ptunnel/jsp/editServer.jsp

    r9a241af r81975e9  
    265265                    <option value="2"<%=(tunnelQuantity == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)")%></option>
    266266                    <option value="3"<%=(tunnelQuantity == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)")%></option>
    267                 <% if (tunnelQuantity > 3) {
    268                 %>    <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> <%=intl._("tunnels")%></option>
     267                    <option value="4"<%=(tunnelQuantity == 4 ? " selected=\"selected\"" : "") %>><%=intl._("4 in, 4 out (high traffic server)")%></option>
     268                    <option value="5"<%=(tunnelQuantity == 5 ? " selected=\"selected\"" : "") %>><%=intl._("5 in, 5 out (high traffic server)")%></option>
     269                    <option value="6"<%=(tunnelQuantity == 6 ? " selected=\"selected\"" : "") %>><%=intl._("6 in, 6 out (high traffic server)")%></option>
     270                <% if (tunnelQuantity > 6) {
     271                %>    <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%>&nbsp;<%=intl._("tunnels")%></option>
    269272                <% }
    270273              %></select>               
  • apps/jetty/apache-tomcat-deployer/NOTICE

    r9a241af r81975e9  
    11Apache Tomcat
    2 Copyright 1999-2011 The Apache Software Foundation
     2Copyright 1999-2012 The Apache Software Foundation
    33
    44This product includes software developed by
  • apps/jetty/apache-tomcat-deployer/README-i2p.txt

    r9a241af r81975e9  
    33
    44Retrieved from the file
    5         apache-tomcat-6.0.35-deployer.tar.gz
     5        apache-tomcat-6.0.36-deployer.tar.gz
    66
    77minus the following files and directores:
Note: See TracChangeset for help on using the changeset viewer.