i2psnark: Add basic search box

searches torrent names only
CSS fixups to follow
This commit is contained in:
zzz
2023-01-17 14:57:47 -05:00
parent 5fbf385805
commit 83677f01fb

View File

@@ -214,7 +214,7 @@ public class I2PSnarkServlet extends BasicServlet {
req.setCharacterEncoding("UTF-8");
String pOverride = _manager.util().connected() ? null : "";
String peerString = getQueryString(req, pOverride, null, null);
String peerString = getQueryString(req, pOverride, null, null, "");
String cspNonce = Integer.toHexString(_context.random().nextInt());
// AJAX for mainsection
@@ -378,9 +378,19 @@ public class I2PSnarkServlet extends BasicServlet {
continue;
if (_manager.util().isKnownOpenTracker(t.announceURL))
continue;
out.write(" <a href=\"" + t.baseURL + "\" class=\"snarkNav nav_tracker\" target=\"_blank\">" + t.name + "</a>");
out.write(" <a href=\"" + t.baseURL + "\" class=\"snarkNav nav_tracker\" target=\"_blank\">" + t.name + "</a>\n");
}
}
if (_manager.getTorrents().size() > 1) {
out.write("<form class=\"search\" id = \"search\" action=\"" + _contextPath + "\" method=\"GET\">" +
"<input type=\"text\" name=\"s\" size=\"20\" class=\"search snarkNav\" id=\"searchbox\"");
String s = req.getParameter("s");
if (s != null)
out.write(" value=\"" + DataHelper.escapeHTML(s) + '"');
out.write(">" +
"<input type=\"reset\" class=\"cancel snarkNav\" value=\"\">" +
"</form>\n");
}
}
out.write("</div>\n");
String newURL = req.getParameter("newURL");
@@ -488,6 +498,17 @@ public class I2PSnarkServlet extends BasicServlet {
boolean isDegraded = ua != null && ServletUtil.isTextBrowser(ua);
boolean noThinsp = isDegraded || (ua != null && ua.startsWith("Opera"));
// search
boolean isSearch = false;
String search = req.getParameter("s");
if (search != null && search.length() > 0) {
List<Snark> matches = search(search, snarks);
if (matches != null) {
snarks = matches;
isSearch = true;
}
}
// pages
int start = 0;
int total = snarks.size();
@@ -743,6 +764,8 @@ public class I2PSnarkServlet extends BasicServlet {
out.write(_t("Unreadable") + ": " + DataHelper.escapeHTML(dd.toString()));
} else if (!canWrite) {
out.write(_t("No write permissions for data directory") + ": " + DataHelper.escapeHTML(dd.toString()));
} else if (isSearch) {
out.write(_t("No torrents found."));
} else {
out.write(_t("No torrents loaded."));
}
@@ -817,6 +840,43 @@ public class I2PSnarkServlet extends BasicServlet {
return start == 0;
}
/**
* search torrents for matching terms
*
* @param search non-null
* @param snarks unmodified
* @return null if no valid search, or matching torrents in same order, empty if no match
* @since 0.9.58
*/
private static List<Snark> search(String search, Collection<Snark> snarks) {
List<String> searchList = null;
String[] terms = DataHelper.split(search, " ");
for (int i = 0; i < terms.length; i++) {
String term = terms[i];
if (term.length() > 0) {
if (searchList == null)
searchList = new ArrayList<String>(4);
searchList.add(term.toLowerCase(Locale.US));
}
}
if (searchList == null)
return null;
List<Snark> matches = new ArrayList<Snark>(32);
for (Snark snark : snarks) {
String lcname = snark.getBaseName().toLowerCase(Locale.US);
// search for any term (OR)
for (int j = 0; j < searchList.size(); j++) {
String term = searchList.get(j);
if (lcname.contains(term)) {
matches.add(snark);
break;
}
}
}
return matches;
}
/**
* hidden inputs for nonce and paramters p, st, and sort
*
@@ -858,11 +918,19 @@ public class I2PSnarkServlet extends BasicServlet {
if (action != null) {
buf.append("<input type=\"hidden\" name=\"action\" value=\"")
.append(action).append("\" >\n");
} else {
// for buttons, keep the search term
String sParam = req.getParameter("s");
if (sParam != null) {
buf.append("<input type=\"hidden\" name=\"s\" value=\"")
.append(DataHelper.escapeHTML(sParam)).append("\" >\n");
}
}
}
/**
* Build HTML-escaped and stripped query string
* Build HTML-escaped and stripped query string.
* Keeps any existing search param.
*
* @param p override or "" for default or null to keep the same as in req
* @param st override or "" for default or null to keep the same as in req
@@ -871,6 +939,14 @@ public class I2PSnarkServlet extends BasicServlet {
* @since 0.9.16
*/
private static String getQueryString(HttpServletRequest req, String p, String st, String so) {
return getQueryString(req, p, st, so, null);
}
/**
* @param s search param override or "" for default or null to keep the same as in req
* @since 0.9.58
*/
private static String getQueryString(HttpServletRequest req, String p, String st, String so, String s) {
StringBuilder buf = new StringBuilder(64);
if (p == null) {
p = req.getParameter("p");
@@ -903,6 +979,18 @@ public class I2PSnarkServlet extends BasicServlet {
buf.append("&amp;st=");
buf.append(st);
}
if (s == null) {
s = req.getParameter("s");
if (s != null)
s = DataHelper.escapeHTML(s);
}
if (s != null && !s.equals("")) {
if (buf.length() <= 0)
buf.append("?s=");
else
buf.append("&amp;s=");
buf.append(s);
}
return buf.toString();
}
@@ -1460,8 +1548,34 @@ public class I2PSnarkServlet extends BasicServlet {
_manager.addMessage(_t("Error creating torrent - you must enter a file or directory"));
}
} else if ("StopAll".equals(action)) {
String search = req.getParameter("s");
if (search != null && search.length() > 0) {
List<Snark> matches = search(search, _manager.getTorrents());
if (matches != null) {
for (Snark snark : matches) {
_manager.stopTorrent(snark, false);
}
return;
}
}
_manager.stopAllTorrents(false);
} else if ("StartAll".equals(action)) {
String search = req.getParameter("s");
if (search != null && search.length() > 0) {
List<Snark> matches = search(search, _manager.getTorrents());
if (matches != null) {
// TODO thread it
int count = 0;
for (Snark snark : matches) {
_manager.startTorrent(snark);
if ((count++ & 0x0f) == 15) {
// try to prevent OOMs
try { Thread.sleep(250); } catch (InterruptedException ie) {}
}
}
return;
}
}
_manager.startAllTorrents();
} else if ("Clear".equals(action)) {
String sid = req.getParameter("id");