forked from I2P_Developers/i2p.i2p
Handle URI encoding, UTF-8, and multiple trackers in magnet links
This commit is contained in:
@@ -4,6 +4,9 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -1647,7 +1650,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param url in base32 or hex, xt must be first magnet param
|
* @param url in base32 or hex
|
||||||
* @since 0.8.4
|
* @since 0.8.4
|
||||||
*/
|
*/
|
||||||
private void addMagnet(String url) {
|
private void addMagnet(String url) {
|
||||||
@@ -1662,7 +1665,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ihash = xt.substring("urn:btih:".length());
|
ihash = xt.substring("urn:btih:".length());
|
||||||
trackerURL = getParam("tr", url);
|
trackerURL = getTrackerParam(url);
|
||||||
name = "Magnet " + ihash;
|
name = "Magnet " + ihash;
|
||||||
String dn = getParam("dn", url);
|
String dn = getParam("dn", url);
|
||||||
if (dn != null)
|
if (dn != null)
|
||||||
@@ -1698,6 +1701,9 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
_manager.addMagnet(name, ih, trackerURL, true);
|
_manager.addMagnet(name, ih, trackerURL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return first decoded parameter or null
|
||||||
|
*/
|
||||||
private static String getParam(String key, String uri) {
|
private static String getParam(String key, String uri) {
|
||||||
int idx = uri.indexOf('?' + key + '=');
|
int idx = uri.indexOf('?' + key + '=');
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
@@ -1715,9 +1721,100 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
rv = rv.substring(0, idx);
|
rv = rv.substring(0, idx);
|
||||||
else
|
else
|
||||||
rv = rv.trim();
|
rv = rv.trim();
|
||||||
|
return decode(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return all decoded parameters or null
|
||||||
|
* @since 0.9.1
|
||||||
|
*/
|
||||||
|
private static List<String> getMultiParam(String key, String uri) {
|
||||||
|
int idx = uri.indexOf('?' + key + '=');
|
||||||
|
if (idx >= 0) {
|
||||||
|
idx += key.length() + 2;
|
||||||
|
} else {
|
||||||
|
idx = uri.indexOf('&' + key + '=');
|
||||||
|
if (idx >= 0)
|
||||||
|
idx += key.length() + 2;
|
||||||
|
}
|
||||||
|
if (idx < 0 || idx > uri.length())
|
||||||
|
return null;
|
||||||
|
List<String> rv = new ArrayList();
|
||||||
|
while (true) {
|
||||||
|
String p = uri.substring(idx);
|
||||||
|
uri = p;
|
||||||
|
idx = p.indexOf('&');
|
||||||
|
if (idx >= 0)
|
||||||
|
p = p.substring(0, idx);
|
||||||
|
else
|
||||||
|
p = p.trim();
|
||||||
|
rv.add(decode(p));
|
||||||
|
idx = uri.indexOf('&' + key + '=');
|
||||||
|
if (idx < 0)
|
||||||
|
break;
|
||||||
|
idx += key.length() + 2;
|
||||||
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return first valid I2P tracker or null
|
||||||
|
* @since 0.9.1
|
||||||
|
*/
|
||||||
|
private static String getTrackerParam(String uri) {
|
||||||
|
List<String> trackers = getMultiParam("tr", uri);
|
||||||
|
if (trackers == null)
|
||||||
|
return null;
|
||||||
|
for (String t : trackers) {
|
||||||
|
try {
|
||||||
|
URI u = new URI(t);
|
||||||
|
String protocol = u.getScheme();
|
||||||
|
String host = u.getHost();
|
||||||
|
if (protocol == null || host == null ||
|
||||||
|
!protocol.toLowerCase(Locale.US).equals("http") ||
|
||||||
|
!host.toLowerCase(Locale.US).endsWith(".i2p"))
|
||||||
|
continue;
|
||||||
|
return t;
|
||||||
|
} catch(URISyntaxException use) {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode %xx encoding, convert to UTF-8 if necessary
|
||||||
|
* Copied from i2ptunnel LocalHTTPServer
|
||||||
|
* @since 0.9.1
|
||||||
|
*/
|
||||||
|
private static String decode(String s) {
|
||||||
|
if (!s.contains("%"))
|
||||||
|
return s;
|
||||||
|
StringBuilder buf = new StringBuilder(s.length());
|
||||||
|
boolean utf8 = false;
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
char c = s.charAt(i);
|
||||||
|
if (c != '%') {
|
||||||
|
buf.append(c);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
int val = Integer.parseInt(s.substring(++i, (++i) + 1), 16);
|
||||||
|
if ((val & 0x80) != 0)
|
||||||
|
utf8 = true;
|
||||||
|
buf.append((char) val);
|
||||||
|
} catch (IndexOutOfBoundsException ioobe) {
|
||||||
|
break;
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (utf8) {
|
||||||
|
try {
|
||||||
|
return new String(buf.toString().getBytes("ISO-8859-1"), "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException uee) {}
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/** copied from ConfigTunnelsHelper */
|
/** copied from ConfigTunnelsHelper */
|
||||||
private static final String HOP = "hop";
|
private static final String HOP = "hop";
|
||||||
private static final String TUNNEL = "tunnel";
|
private static final String TUNNEL = "tunnel";
|
||||||
|
Reference in New Issue
Block a user