[tor-commits] [onionoo/master] Support searches by space-separated fingerprint.

karsten at torproject.org karsten at torproject.org
Sun Nov 15 19:52:50 UTC 2015


commit 56e0e019edd0721bf725fd7699a316a3c90ffd16
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Sat Oct 10 12:38:57 2015 +0200

    Support searches by space-separated fingerprint.
    
    Includes suggestions by iwakeh, including using String[] instead of
    HashSet<String> for lower memory requirements.
    
    Implements #17115.
---
 build.xml                                          |    2 +-
 .../torproject/onionoo/docs/SummaryDocument.java   |   16 +++++++++
 .../torproject/onionoo/server/RequestHandler.java  |   10 ++++++
 .../torproject/onionoo/server/ResponseBuilder.java |    4 +--
 .../onionoo/docs/SummaryDocumentTest.java          |   38 ++++++++++++++++++++
 .../onionoo/server/ResourceServletTest.java        |   20 +++++++++++
 web/protocol.html                                  |   19 +++++-----
 7 files changed, 96 insertions(+), 13 deletions(-)

diff --git a/build.xml b/build.xml
index 03a97f1..de5d84a 100644
--- a/build.xml
+++ b/build.xml
@@ -1,6 +1,6 @@
 <project default="dist" name="onionoo" basedir=".">
 
-  <property name="onionoo.protocol.version" value="2.6"/>
+  <property name="onionoo.protocol.version" value="3.0"/>
   <property name="release.version"
             value="${onionoo.protocol.version}.0"/>
   <property name="javasources" value="src/main/java"/>
diff --git a/src/main/java/org/torproject/onionoo/docs/SummaryDocument.java b/src/main/java/org/torproject/onionoo/docs/SummaryDocument.java
index ae7202b..0c217c1 100644
--- a/src/main/java/org/torproject/onionoo/docs/SummaryDocument.java
+++ b/src/main/java/org/torproject/onionoo/docs/SummaryDocument.java
@@ -68,6 +68,22 @@ public class SummaryDocument extends Document {
     return this.base64Fingerprint;
   }
 
+  private transient String[] fingerprintSortedHexBlocks = null;
+  public String[] getFingerprintSortedHexBlocks() {
+    if (this.fingerprintSortedHexBlocks == null && this.f != null) {
+      String fingerprint = this.f.toUpperCase();
+      String[] fingerprintSortedHexBlocks =
+          new String[fingerprint.length() / 4];
+      for (int i = 0; i < fingerprint.length(); i += 4) {
+        fingerprintSortedHexBlocks[i / 4] = fingerprint.substring(
+            i, Math.min(i + 4, fingerprint.length()));
+      }
+      Arrays.sort(fingerprintSortedHexBlocks);
+      this.fingerprintSortedHexBlocks = fingerprintSortedHexBlocks;
+    }
+    return this.fingerprintSortedHexBlocks;
+  }
+
   private String n;
   public void setNickname(String nickname) {
     if (nickname == null || nickname.equals("Unnamed")) {
diff --git a/src/main/java/org/torproject/onionoo/server/RequestHandler.java b/src/main/java/org/torproject/onionoo/server/RequestHandler.java
index 2d8dd58..bd75992 100644
--- a/src/main/java/org/torproject/onionoo/server/RequestHandler.java
+++ b/src/main/java/org/torproject/onionoo/server/RequestHandler.java
@@ -3,6 +3,7 @@
 package org.torproject.onionoo.server;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -209,6 +210,8 @@ public class RequestHandler {
       SummaryDocument entry = e.getValue();
       String base64Fingerprint = entry.isRelay() ?
           entry.getBase64Fingerprint() : null;
+      String[] fingerprintSortedHexBlocks =
+          entry.getFingerprintSortedHexBlocks();
       boolean lineMatches = false;
       String nickname = entry.getNickname() != null ?
           entry.getNickname().toLowerCase() : "unnamed";
@@ -229,6 +232,13 @@ public class RequestHandler {
           base64Fingerprint.startsWith(searchTerm)) {
         /* Base64-encoded fingerprint matches. */
         lineMatches = true;
+      } else if (searchTerm.length() == 4 &&
+          fingerprintSortedHexBlocks != null &&
+          Arrays.binarySearch(fingerprintSortedHexBlocks,
+              searchTerm.toUpperCase()) >= 0) {
+        /* 4-hex-character block of space-separated fingerprint
+         * matches. */
+        lineMatches = true;
       } else {
         List<String> addresses = entry.getAddresses();
         for (String address : addresses) {
diff --git a/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java b/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java
index e7c614a..4afa782 100644
--- a/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java
+++ b/src/main/java/org/torproject/onionoo/server/ResponseBuilder.java
@@ -70,9 +70,9 @@ public class ResponseBuilder {
     return this.charsWritten;
   }
 
-  private static final String PROTOCOL_VERSION = "2.6";
+  private static final String PROTOCOL_VERSION = "3.0";
 
-  private static final String NEXT_MAJOR_VERSION_SCHEDULED = "2015-11-15";
+  private static final String NEXT_MAJOR_VERSION_SCHEDULED = null;
 
   private void writeRelays(List<SummaryDocument> relays, PrintWriter pw) {
     String nextMajorVersionScheduledLine =
diff --git a/src/test/java/org/torproject/onionoo/docs/SummaryDocumentTest.java b/src/test/java/org/torproject/onionoo/docs/SummaryDocumentTest.java
new file mode 100644
index 0000000..f25528c
--- /dev/null
+++ b/src/test/java/org/torproject/onionoo/docs/SummaryDocumentTest.java
@@ -0,0 +1,38 @@
+/* Copyright 2015 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.onionoo.docs;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.TreeSet;
+
+import org.junit.Test;
+
+public class SummaryDocumentTest {
+
+  @Test()
+  public void testFingerprintSortedHexBlocksAreSorted() {
+    SummaryDocument relayTorkaZ = new SummaryDocument(true, "TorkaZ",
+        "000C5F55BD4814B917CC474BD537F1A3B33CCE2A", Arrays.asList(
+        new String[] { "62.216.201.221", "62.216.201.222",
+        "62.216.201.223" }), DateTimeHelper.parse("2013-04-19 05:00:00"),
+        false, new TreeSet<String>(Arrays.asList(new String[] { "Running",
+        "Valid" })), 20L, "de",
+        DateTimeHelper.parse("2013-04-18 05:00:00"), "AS8767",
+        "torkaz <klaus dot zufall at gmx dot de> "
+        + "<fb-token:np5_g_83jmf=>", new TreeSet<String>(Arrays.asList(
+        new String[] { "001C13B3A55A71B977CA65EC85539D79C653A3FC",
+        "0025C136C1F3A9EEFE2AE3F918F03BFA21B5070B" })),
+        new TreeSet<String>(Arrays.asList(
+        new String[] { "001C13B3A55A71B977CA65EC85539D79C653A3FC" })));
+    String[] fingerprintSortedHexBlocks =
+        relayTorkaZ.getFingerprintSortedHexBlocks();
+    for (int i = 0; i < fingerprintSortedHexBlocks.length - 1; i++) {
+      assertTrue("Hex blocks not in sorted order",
+          fingerprintSortedHexBlocks[i].compareTo(
+          fingerprintSortedHexBlocks[i + 1]) <= 0);
+    }
+  }
+}
+
diff --git a/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java b/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
index f52413a..8370b16 100644
--- a/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
+++ b/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
@@ -611,6 +611,26 @@ public class ResourceServletTest {
   }
 
   @Test()
+  public void testSearchSpaceSeparatedFingerprintFourty() {
+    this.assertSummaryDocument(
+        "/summary?search=000C 5F55 BD48 14B9 17CC 474B D537 F1A3 B33C "
+        + "CE2A", 1, new String[] { "TorkaZ" }, 0, null);
+  }
+
+  @Test()
+  public void testSearchSpaceSeparatedFingerprintLastEight() {
+    this.assertSummaryDocument(
+        "/summary?search=F1A3 B33C", 1, new String[] { "TorkaZ" }, 0,
+        null);
+  }
+
+  @Test()
+  public void testSearchSpaceSeparatedFingerprintLastThree() {
+    this.assertSummaryDocument(
+        "/summary?search=33C", 0, null, 0, null);
+  }
+
+  @Test()
   public void testSearchIp() {
     this.assertSummaryDocument(
         "/summary?search=62.216.201.221", 1, new String[] { "TorkaZ" }, 0,
diff --git a/web/protocol.html b/web/protocol.html
index 1ca14d1..e18afea 100644
--- a/web/protocol.html
+++ b/web/protocol.html
@@ -183,9 +183,8 @@ documents on August 13, 2015.</li>
 <li><strong>2.6</strong>: Added optional "alleged_family" and
 "indirect_family" fields and deprecated optional "family" field in details
 documents on August 25, 2015.</li>
-<li><strong>3.0</strong> (scheduled, but not deployed yet!): Extend search
-parameter to match any 4 hex characters of a space-separated fingerprint,
-to be deployed by November 15, 2015.</li>
+<li><strong>3.0</strong>: Extended search parameter to match any 4 hex
+characters of a space-separated fingerprint on November 15, 2015.</li>
 </ul>
 
 </div> <!-- box -->
@@ -289,13 +288,13 @@ Parameter values are case-insensitive.
 <li>
 <b>search</b>
 <p>
-Return only (1) relays with the parameter value
-matching (part of a) nickname, (possibly $-prefixed) beginning of a
-hex-encoded fingerprint, beginning of a base64-encoded fingerprint
-without trailing equal signs, or beginning of an IP address, (2) bridges
-with (part of a) nickname or (possibly $-prefixed) beginning of a hashed
-hex-encoded fingerprint, and (3) relays and/or bridges matching a given
-qualified search term.
+Return only (1) relays with the parameter value matching (part of a)
+nickname, (possibly $-prefixed) beginning of a hex-encoded fingerprint,
+any 4 hex characters of a space-separated fingerprint, beginning of a
+base64-encoded fingerprint without trailing equal signs, or beginning of
+an IP address, (2) bridges with (part of a) nickname or (possibly
+$-prefixed) beginning of a hashed hex-encoded fingerprint, and (3) relays
+and/or bridges matching a given qualified search term.
 Searches by relay IP address include all known addresses used for onion
 routing and for exiting to the Internet.
 Searches for beginnings of IP addresses are performed on textual



More information about the tor-commits mailing list