diff --git a/core/src/main/java/com/muwire/core/Persona.java b/core/src/main/java/com/muwire/core/Persona.java index b280dd62..70a3a910 100644 --- a/core/src/main/java/com/muwire/core/Persona.java +++ b/core/src/main/java/com/muwire/core/Persona.java @@ -68,6 +68,10 @@ public class Persona { humanReadableName = name.getName() + "@" + destination.toBase32().substring(0,32); return humanReadableName; } + + public Destination getDestination() { + return destination; + } public String toBase64() throws DataFormatException, IOException { if (base64 == null) { diff --git a/webui/src/main/java/com/muwire/webui/MuWireClient.java b/webui/src/main/java/com/muwire/webui/MuWireClient.java index 90a871ad..9d843c9b 100644 --- a/webui/src/main/java/com/muwire/webui/MuWireClient.java +++ b/webui/src/main/java/com/muwire/webui/MuWireClient.java @@ -18,6 +18,7 @@ import javax.servlet.ServletContext; import com.muwire.core.Core; import com.muwire.core.MuWireSettings; +import com.muwire.core.search.UIResultBatchEvent; import net.i2p.app.ClientAppManager; import net.i2p.app.ClientAppState; @@ -107,7 +108,11 @@ public class MuWireClient { void setCore(Core core) { this.core = core; servletContext.setAttribute("core", core); - servletContext.setAttribute("searchManager", new SearchManager(core)); + + SearchManager searchManager = new SearchManager(core); + core.getEventBus().register(UIResultBatchEvent.class, searchManager); + + servletContext.setAttribute("searchManager", searchManager); } public String getHome() { diff --git a/webui/src/main/java/com/muwire/webui/SearchManager.java b/webui/src/main/java/com/muwire/webui/SearchManager.java index 176c8199..3ca93e2c 100644 --- a/webui/src/main/java/com/muwire/webui/SearchManager.java +++ b/webui/src/main/java/com/muwire/webui/SearchManager.java @@ -1,27 +1,101 @@ package com.muwire.webui; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import java.util.UUID; import com.muwire.core.Core; +import com.muwire.core.SplitPattern; +import com.muwire.core.search.QueryEvent; +import com.muwire.core.search.SearchEvent; +import com.muwire.core.search.UIResultBatchEvent; +import com.muwire.core.util.DataUtil; + +import net.i2p.crypto.DSAEngine; +import net.i2p.data.Base64; +import net.i2p.data.Signature; class SearchManager { private final Core core; - private final Set searches = new HashSet<>(); + private final Map results = new HashMap<>(); SearchManager(Core core) { this.core = core; } void newSearch(String search) { - searches.add(search); + search = search.trim(); + if (search.length() == 0) + return; + if (search.length() > 128) { + // TODO: browse by persona + } else { + UUID uuid = UUID.randomUUID(); + + SearchResults searchResults = new SearchResults(uuid, search); + results.put(uuid, searchResults); + + boolean hashSearch = false; + byte [] root = null; + if (search.length() == 44 && search.indexOf(' ') < 0) { + try { + root = Base64.decode(search); + hashSearch = true; + } catch (Exception e) { + // not a hash search + } + } + SearchEvent searchEvent = new SearchEvent(); + searchEvent.setOobInfohash(true); + searchEvent.setCompressedResults(true); + searchEvent.setPersona(core.getMe()); + searchEvent.setUuid(uuid); + byte[] payload; + if (hashSearch) { + searchEvent.setSearchHash(root); + payload = root; + } else { + String[] nonEmpty = SplitPattern.termify(search); + payload = String.join(" ", nonEmpty).getBytes(StandardCharsets.UTF_8); + searchEvent.setSearchTerms(Arrays.asList(nonEmpty)); + searchEvent.setSearchComments(core.getMuOptions().getSearchComments()); + } + + boolean firstHop = core.getMuOptions().allowUntrusted() || core.getMuOptions().getSearchExtraHop(); + + Signature sig = DSAEngine.getInstance().sign(payload, core.getSpk()); + + long timestamp = System.currentTimeMillis(); + QueryEvent queryEvent = new QueryEvent(); + queryEvent.setSearchEvent(searchEvent); + queryEvent.setFirstHop(firstHop); + queryEvent.setReplyTo(core.getMe().getDestination()); + queryEvent.setReceivedOn(core.getMe().getDestination()); + queryEvent.setOriginator(core.getMe()); + queryEvent.setSig(sig.getData()); + queryEvent.setQueryTime(timestamp); + queryEvent.setSig2(DataUtil.signUUID(uuid, timestamp, core.getSpk())); + + core.getEventBus().publish(queryEvent); + } } - Iterable getSearches() { - return searches; + Iterable getSearches() { + return results.values(); } + public void onUIResultBatchEvent(UIResultBatchEvent e) { + UUID uuid = e.getResults()[0].getUuid(); + SearchResults searchResults = results.get(uuid); + if (searchResults == null) + return; // oh well + searchResults.addResults(e); + } } diff --git a/webui/src/main/java/com/muwire/webui/SearchResults.java b/webui/src/main/java/com/muwire/webui/SearchResults.java new file mode 100644 index 00000000..566a9e9d --- /dev/null +++ b/webui/src/main/java/com/muwire/webui/SearchResults.java @@ -0,0 +1,48 @@ +package com.muwire.webui; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import com.muwire.core.Persona; +import com.muwire.core.search.UIResultBatchEvent; +import com.muwire.core.search.UIResultEvent; + +public class SearchResults { + + private final UUID uuid; + private final String search; + private final Map> bySender = new ConcurrentHashMap<>(); + + public SearchResults(UUID uuid, String search) { + this.uuid = uuid; + this.search = search; + } + + void addResults(UIResultBatchEvent e) { + Persona sender = e.getResults()[0].getSender(); + Set existing = bySender.get(sender); + if (existing == null) { + existing = new HashSet<>(); + bySender.put(sender, existing); + } + existing.addAll(Arrays.asList(e.getResults())); + } + + public UUID getUUID() { + return uuid; + } + + public String getSearch() { + return search; + } + + public Map> getBySender() { + return bySender; + } + +} diff --git a/webui/src/main/webapp/Home.jsp b/webui/src/main/webapp/Home.jsp index 18d84140..83901b38 100644 --- a/webui/src/main/webapp/Home.jsp +++ b/webui/src/main/webapp/Home.jsp @@ -3,6 +3,8 @@ <%@ page import="java.io.File" %> <%@ page import="java.util.*" %> <%@ page import="com.muwire.webui.*" %> +<%@ page import="com.muwire.core.*" %> +<%@ page import="com.muwire.core.search.*" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> @@ -31,8 +33,18 @@ Active Searches:
<% SearchManager searchManager = (SearchManager) client.getServletContext().getAttribute("searchManager"); - for (String search : searchManager.getSearches()) { - out.print(search); + for (SearchResults results : searchManager.getSearches()) { + out.print(results.getSearch()); + out.print(" senders: "); + Map> bySender = results.getBySender(); + out.print(bySender.size()); + + int total = 0; + for (Set s : bySender.values()) { + total += s.size(); + } + out.print(" results: "); + out.print(total); out.print("
"); } %>