Changeset ddc329e8


Ignore:
Timestamp:
May 30, 2012 7:45:45 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
f14ff31
Parents:
8453c34b
Message:

Handle URI encoding, UTF-8, and multiple trackers in magnet links

File:
1 edited

Legend:

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

    r8453c34b rddc329e8  
    55import java.io.IOException;
    66import java.io.PrintWriter;
     7import java.io.UnsupportedEncodingException;
     8import java.net.URI;
     9import java.net.URISyntaxException;
    710import java.text.Collator;
    811import java.text.DecimalFormat;
     
    16481651
    16491652    /**
    1650      *  @param url in base32 or hex, xt must be first magnet param
     1653     *  @param url in base32 or hex
    16511654     *  @since 0.8.4
    16521655     */
     
    16631666            }
    16641667            ihash = xt.substring("urn:btih:".length());
    1665             trackerURL = getParam("tr", url);
     1668            trackerURL = getTrackerParam(url);
    16661669            name = "Magnet " + ihash;
    16671670            String dn = getParam("dn", url);
     
    16991702    }
    17001703
     1704    /**
     1705     *  @return first decoded parameter or null
     1706     */
    17011707    private static String getParam(String key, String uri) {
    17021708        int idx = uri.indexOf('?' + key + '=');
     
    17161722        else
    17171723            rv = rv.trim();
     1724        return decode(rv);
     1725    }
     1726
     1727    /**
     1728     *  @return all decoded parameters or null
     1729     *  @since 0.9.1
     1730     */
     1731    private static List<String> getMultiParam(String key, String uri) {
     1732        int idx = uri.indexOf('?' + key + '=');
     1733        if (idx >= 0) {
     1734            idx += key.length() + 2;
     1735        } else {
     1736            idx = uri.indexOf('&' + key + '=');
     1737            if (idx >= 0)
     1738                idx += key.length() + 2;
     1739        }
     1740        if (idx < 0 || idx > uri.length())
     1741            return null;
     1742        List<String> rv = new ArrayList();
     1743        while (true) {
     1744            String p = uri.substring(idx);
     1745            uri = p;
     1746            idx = p.indexOf('&');
     1747            if (idx >= 0)
     1748                p = p.substring(0, idx);
     1749            else
     1750                p = p.trim();
     1751            rv.add(decode(p));
     1752            idx = uri.indexOf('&' + key + '=');
     1753            if (idx < 0)
     1754                break;
     1755            idx += key.length() + 2;
     1756        }
    17181757        return rv;
     1758    }
     1759
     1760    /**
     1761     *  @return first valid I2P tracker or null
     1762     *  @since 0.9.1
     1763     */
     1764    private static String getTrackerParam(String uri) {
     1765        List<String> trackers = getMultiParam("tr", uri);
     1766        if (trackers == null)
     1767            return null;
     1768        for (String t : trackers) {
     1769            try {
     1770                URI u = new URI(t);
     1771                String protocol = u.getScheme();
     1772                String host = u.getHost();
     1773                if (protocol == null || host == null ||
     1774                    !protocol.toLowerCase(Locale.US).equals("http") ||
     1775                    !host.toLowerCase(Locale.US).endsWith(".i2p"))
     1776                    continue;
     1777                return t;
     1778            } catch(URISyntaxException use) {}
     1779        }
     1780        return null;
     1781    }
     1782
     1783    /**
     1784     *  Decode %xx encoding, convert to UTF-8 if necessary
     1785     *  Copied from i2ptunnel LocalHTTPServer
     1786     *  @since 0.9.1
     1787     */
     1788    private static String decode(String s) {
     1789        if (!s.contains("%"))
     1790            return s;
     1791        StringBuilder buf = new StringBuilder(s.length());
     1792        boolean utf8 = false;
     1793        for (int i = 0; i < s.length(); i++) {
     1794            char c = s.charAt(i);
     1795            if (c != '%') {
     1796                buf.append(c);
     1797            } else {
     1798                try {
     1799                    int val = Integer.parseInt(s.substring(++i, (++i) + 1), 16);
     1800                    if ((val & 0x80) != 0)
     1801                        utf8 = true;
     1802                    buf.append((char) val);
     1803                } catch (IndexOutOfBoundsException ioobe) {
     1804                    break;
     1805                } catch (NumberFormatException nfe) {
     1806                    break;
     1807                }
     1808            }
     1809        }
     1810        if (utf8) {
     1811            try {
     1812                return new String(buf.toString().getBytes("ISO-8859-1"), "UTF-8");
     1813            } catch (UnsupportedEncodingException uee) {}
     1814        }
     1815        return buf.toString();
    17191816    }
    17201817
Note: See TracChangeset for help on using the changeset viewer.