Changeset 4e558320


Ignore:
Timestamp:
Dec 10, 2012 10:48:44 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
7ea1bff
Parents:
9f6ebd8e
Message:
  • i2psnark: Add announce list support (BEP 12) (ticket #778) Preliminary. Still todo: TrackerClient?
Location:
apps/i2psnark/java/src/org/klomp/snark
Files:
4 edited

Legend:

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

    r9f6ebd8e r4e558320  
    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

    r9f6ebd8e r4e558320  
    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

    r9f6ebd8e r4e558320  
    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/web/I2PSnarkServlet.java

    r9f6ebd8e r4e558320  
    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                }
Note: See TracChangeset for help on using the changeset viewer.