[tor-commits] [exonerator/master] Separate response-writing parts from other parts.

karsten at torproject.org karsten at torproject.org
Mon Jul 13 21:09:05 UTC 2015


commit 9d6a0a6b73c237ccb980c67091fbf28cb4f8fd45
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Mon Jul 13 23:04:05 2015 +0200

    Separate response-writing parts from other parts.
---
 .../torproject/exonerator/ExoneraTorServlet.java   |  464 +++++++++++---------
 1 file changed, 264 insertions(+), 200 deletions(-)

diff --git a/src/org/torproject/exonerator/ExoneraTorServlet.java b/src/org/torproject/exonerator/ExoneraTorServlet.java
index 04e87f2..fd7fe8e 100644
--- a/src/org/torproject/exonerator/ExoneraTorServlet.java
+++ b/src/org/torproject/exonerator/ExoneraTorServlet.java
@@ -1,4 +1,4 @@
-/* Copyright 2011, 2012 The Tor Project
+/* Copyright 2011--2015 The Tor Project
  * See LICENSE for licensing information */
 package org.torproject.exonerator;
 
@@ -56,78 +56,13 @@ public class ExoneraTorServlet extends HttpServlet {
     }
   }
 
-  private void writeHeader(PrintWriter out) throws IOException {
-    out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 "
-          + "Transitional//EN\">\n"
-        + "<html>\n"
-        + "  <head>\n"
-        + "    <title>ExoneraTor</title>\n"
-        + "    <meta http-equiv=\"content-type\" content=\"text/html; "
-          + "charset=ISO-8859-1\">\n"
-        + "    <link href=\"/css/stylesheet-ltr.css\" type=\"text/css\" "
-          + "rel=\"stylesheet\">\n"
-        + "    <link href=\"/images/favicon.ico\" "
-          + "type=\"image/x-icon\" rel=\"shortcut icon\">\n"
-        + "  </head>\n"
-        + "  <body>\n"
-        + "    <div class=\"center\">\n"
-        + "      <div class=\"main-column\" style=\"margin:5; "
-          + "Padding:0;\">\n"
-        + "        <h2>ExoneraTor</h2>\n"
-        + "        <h3>or: a website that tells you whether a given IP "
-          + "address was a Tor relay</h3>\n"
-        + "        <br>\n"
-        + "        <p>Just because you see an Internet connection from a "
-          + "particular IP address does not mean you know <i>who</i> "
-          + "originated the traffic. Tor anonymizes Internet traffic by "
-          + "\"<a href=\"https://www.torproject.org/about/overview"
-          + "#thesolution\">onion routing</a>,\" sending packets "
-          + "through a series of encrypted hops before they reach their "
-          + "destination. Therefore, if you see traffic from a Tor node, "
-          + "you may be seeing traffic that originated from someone "
-          + "using Tor, rather than from the node operator itself. The "
-          + "Tor Project and Tor node operators have no records of the "
-          + "traffic that passes over the network, but we do maintain "
-          + "current and historical records of which IP addresses are "
-          + "part of the Tor network.</p>\n"
-        + "        <br>\n"
-        + "        <p>ExoneraTor tells you whether there was a Tor relay "
-          + "running on a given IP address at a given time. ExoneraTor "
-          + "learns these facts by parsing the public relay lists that "
-          + "are collected from the Tor directory authorities and the "
-          + "exit lists collected by TorDNSEL. By inputting an IP "
-          + "address and time, you can determine whether that IP was "
-          + "then a part of the Tor network.</p>\n"
-        + "        <br>\n"
-        + "        <p><font color=\"red\"><b>Notice:</b> Note that the "
-          + "information you are providing below may be visible to "
-          + "anyone who can read the network traffic between you and "
-          + "this web server or who has access to this web "
-          + "server.</font></p>\n"
-        + "        <br>\n");
-  }
-
-  private void writeFooter(PrintWriter out) throws IOException {
-    out.println("        <br>\n"
-        + "      </div>\n"
-        + "    </div>\n"
-        + "    <div class=\"bottom\" id=\"bottom\">\n"
-        + "      <p>\"Tor\" and the \"Onion Logo\" are <a "
-          + "href=\"https://www.torproject.org/docs/trademark-faq.html.en"
-          + "\">registered trademarks</a> of The Tor Project, Inc.</p>\n"
-        + "    </div>\n"
-        + "  </body>\n"
-        + "</html>");
-    out.close();
-  }
-
   public void doGet(HttpServletRequest request,
       HttpServletResponse response) throws IOException,
       ServletException {
 
     /* Start writing response. */
     PrintWriter out = response.getWriter();
-    writeHeader(out);
+    this.writeHeader(out);
 
     /* Open a database connection that we'll use to handle the whole
      * request. */
@@ -136,11 +71,8 @@ public class ExoneraTorServlet extends HttpServlet {
     try {
       conn = this.ds.getConnection();
     } catch (SQLException e) {
-      out.println("<p><font color=\"red\"><b>Warning: </b></font>Unable "
-          + "to connect to the database. If this problem persists, "
-          + "please <a href=\"mailto:tor-assistants at torproject.org\">let "
-          + "us know</a>!</p>\n");
-      writeFooter(out);
+      this.writeUnableToConnectToDatabaseWarning(out);
+      this.writeFooter(out);
       return;
     }
 
@@ -163,12 +95,8 @@ public class ExoneraTorServlet extends HttpServlet {
       /* Looks like we don't have any consensuses. */
     }
     if (firstValidAfter < 0L || lastValidAfter < 0L) {
-      out.println("<p><font color=\"red\"><b>Warning: </b></font>This "
-          + "server doesn't have any relay lists available. If this "
-          + "problem persists, please "
-          + "<a href=\"mailto:tor-assistants at lists.torproject.org\">let "
-          + "us know</a>!</p>\n");
-      writeFooter(out);
+      this.writeNoDataWarning(out);
+      this.writeFooter(out);
       try {
         conn.close();
         this.logger.info("Returned a database connection to the pool "
@@ -179,9 +107,6 @@ public class ExoneraTorServlet extends HttpServlet {
       return;
     }
 
-    out.println("<a name=\"relay\"></a><h3>Was there a Tor relay running "
-        + "on this IP address?</h3>");
-
     /* Parse IP parameter. */
     Pattern ipv4AddressPattern = Pattern.compile(
         "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
@@ -283,47 +208,11 @@ public class ExoneraTorServlet extends HttpServlet {
     }
 
     /* Write form with IP address and timestamp. */
-    out.println("        <form action=\"#relay\">\n"
-        + "          <table>\n"
-        + "            <tr>\n"
-        + "              <td align=\"right\">IP address in question:"
-          + "</td>\n"
-        + "              <td><input type=\"text\" name=\"ip\" size=\"30\""
-          + (relayIP.length() > 0 ? " value=\"" + relayIP + "\""
-            : "")
-          + ">"
-          + (ipWarning.length() > 0 ? "<br><font color=\"red\">"
-          + ipWarning + "</font>" : "")
-        + "</td>\n"
-        + "              <td><i>(Ex.: 86.59.21.38 or "
-          + "2001:858:2:2:aabb:0:563b:1526)</i></td>\n"
-        + "            </tr>\n"
-        + "            <tr>\n"
-        + "              <td align=\"right\">Date:</td>\n"
-        + "              <td><input type=\"text\" name=\"timestamp\""
-          + " size=\"30\""
-          + (timestampStr.length() > 0 ? " value=\"" + timestampStr + "\""
-            : "")
-          + ">"
-          + (timestampWarning.length() > 0 ? "<br><font color=\"red\">"
-              + timestampWarning + "</font>" : "")
-        + "</td>\n"
-        + "              <td><i>(Ex.: 2010-01-01)"
-          + "</i></td>\n"
-        + "            </tr>\n"
-        + "            <tr>\n"
-        + "              <td></td>\n"
-        + "              <td>\n"
-        + "                <input type=\"submit\">\n"
-        + "                <input type=\"reset\">\n"
-        + "              </td>\n"
-        + "              <td></td>\n"
-        + "            </tr>\n"
-        + "          </table>\n"
-        + "        </form>\n");
+    this.writeForm(out, relayIP, ipWarning, timestampStr,
+        timestampWarning);
 
     if (relayIP.length() < 1 || timestamp < 1) {
-      writeFooter(out);
+      this.writeFooter(out);
       try {
         conn.close();
         this.logger.info("Returned a database connection to the pool "
@@ -334,19 +223,12 @@ public class ExoneraTorServlet extends HttpServlet {
       return;
     }
 
-    out.printf("<p>Looking up IP address %s in the relay lists "
-        + "published ", relayIP);
     long timestampFrom, timestampTo;
     /* Consider all consensuses published on or within a day of the given
      * date. */
     timestampFrom = timestamp - 24L * 60L * 60L * 1000L;
     timestampTo = timestamp + 2 * 24L * 60L * 60L * 1000L - 1L;
-    out.printf("on or within a day of %s", timestampStr);
-    out.print(" as well as in the relevant exit lists. Clients could "
-        + "have selected any of these relays to build circuits. "
-        + "You may follow the links to relay lists and relay descriptors "
-        + "to grep for the lines printed below and confirm that results "
-        + "are correct.<br>\n");
+    this.writeSearchInfos(out, relayIP, timestampStr);
     SimpleDateFormat validAfterTimeFormat = new SimpleDateFormat(
         "yyyy-MM-dd HH:mm:ss");
     validAfterTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
@@ -370,17 +252,8 @@ public class ExoneraTorServlet extends HttpServlet {
        * interval. */
     }
     if (relevantConsensuses.isEmpty()) {
-      out.println("        <p>No relay lists found!</p>\n"
-          + "        <p>Result is INDECISIVE!</p>\n"
-          + "        <p>We cannot make any statement whether there was "
-          + "a Tor relay running on IP address " + relayIP + " on "
-          + timestampStr + "! We "
-          + "did not find any relevant relay lists on or within a day of "
-          + "the given date. If "
-          + "you think this is an error on our side, please "
-          + "<a href=\"mailto:tor-assistants at torproject.org\">contact "
-          + "us</a>!</p>\n");
-      writeFooter(out);
+      this.writeNoDataForThisInterval(out, relayIP, timestampStr);
+      this.writeFooter(out);
       try {
         conn.close();
         this.logger.info("Returned a database connection to the pool "
@@ -394,7 +267,7 @@ public class ExoneraTorServlet extends HttpServlet {
     /* Search for status entries with the given IP address as onion
      * routing address, plus status entries of relays having an exit list
      * entry with the given IP address as exit address. */
-    SortedSet<String> tableRows = new TreeSet<String>();
+    List<String[]> tableRows = new ArrayList<String[]>();
     try {
       CallableStatement cs = conn.prepareCall(
           "{call search_statusentries_by_address_date(?, ?)}");
@@ -408,7 +281,7 @@ public class ExoneraTorServlet extends HttpServlet {
         SortedSet<String> addresses = new TreeSet<String>();
         long validafter = rs.getTimestamp(3, utcCalendar).getTime();
         String validAfterString = validAfterTimeFormat.format(validafter);
-        String fingerprint = rs.getString(4);
+        String fingerprint = rs.getString(4).toUpperCase();
         String nickname = "(Unknown)";
         String exit = "Unknown";
         for (String line : new String(rawstatusentry).split("\n")) {
@@ -428,15 +301,14 @@ public class ExoneraTorServlet extends HttpServlet {
         if (exitaddress != null && exitaddress.length() > 0) {
           addresses.add(exitaddress);
         }
-        StringBuilder html = new StringBuilder();
-        html.append("<tr><td>" + validAfterString + "</td><td>");
+        StringBuilder sb = new StringBuilder();
         int writtenAddresses = 0;
         for (String address : addresses) {
-          html.append((writtenAddresses++ > 0 ? ", " : "") + address);
+          sb.append((writtenAddresses++ > 0 ? ", " : "") + address);
         }
-        html.append("</td><td>" + fingerprint.toUpperCase() + "</td><td>"
-            + nickname + "</td><td>" + exit + "</td></tr>\n");
-        tableRows.add(html.toString());
+        String[] tableRow = new String[] { validAfterString,
+            sb.toString(), fingerprint, nickname, exit };
+        tableRows.add(tableRow);
       }
       rs.close();
       cs.close();
@@ -446,26 +318,8 @@ public class ExoneraTorServlet extends HttpServlet {
 
     /* Print out what we found. */
     if (!tableRows.isEmpty()) {
-      out.print("<br>\n");
-      out.print("<table>\n");
-      out.print("<thead>\n");
-      out.print("<tr><th>Timestamp (UTC)</th><th>IP address(es)</th>"
-          + "<th>Identity fingerprint</th><th>Nickname</th><th>Exit</th>"
-          + "</tr>\n");
-      out.print("</thead>\n");
-      out.print("<tbody>\n");
-      for (String tableRow : tableRows) {
-        out.print(tableRow);
-      }
-      out.print("</tbody>\n");
-      out.print("</table>\n");
+      this.writeResultsTable(out, tableRows);
     } else {
-      out.printf("        <p>None found!</p>\n"
-          + "        <p>Result is NEGATIVE with high certainty!</p>\n"
-          + "        <p>We did not find IP "
-          + "address " + relayIP + " in any of the relay or exit lists "
-          + "that were published on or within a day of %s.</p>\n",
-          timestampStr);
       /* Run another query to find out if there are relays running on
        * other IP addresses in the same /24 or /48 network and tell the
        * user about it. */
@@ -542,27 +396,13 @@ public class ExoneraTorServlet extends HttpServlet {
           }
         }
       }
-      if (!addressesInSameNetwork.isEmpty()) {
-        if (!relayIP.contains(":")) {
-          out.print("        <p>The following other IP addresses of Tor "
-              + "relays in the same /24 network were found in relay "
-              + "and/or exit lists on or within a day of " + timestampStr
-              + " that could be related "
-              + "to IP address " + relayIP + ":</p>\n");
-        } else {
-          out.print("        <p>The following other IP addresses of Tor "
-              + "relays in the same /48 network were found in relay "
-              + "lists on or within a day of " + timestampStr
-              + " that could be related to IP "
-              + "address " + relayIP + ":</p>\n");
-        }
-        out.print("        <ul>\n");
-        for (String s : addressesInSameNetwork) {
-          out.print("        <li>" + s + "</li>\n");
-        }
-        out.print("        </ul>\n");
+      if (addressesInSameNetwork.isEmpty()) {
+        this.writeNoneFound(out, relayIP, timestampStr);
+      } else {
+        this.writeAddressesInSameNetwork(out, relayIP, timestampStr,
+            addressesInSameNetwork);
       }
-      writeFooter(out);
+      this.writeFooter(out);
       try {
         conn.close();
         this.logger.info("Returned a database connection to the pool "
@@ -575,20 +415,9 @@ public class ExoneraTorServlet extends HttpServlet {
 
     /* Print out result. */
     if (!tableRows.isEmpty()) {
-      out.print("        <p>Result is POSITIVE with high certainty!"
-            + "</p>\n"
-          + "        <p>We found one or more relays on IP address "
-          + relayIP + " in a ");
-      out.print("relay list published on or within a day of "
-          + timestampStr);
-      out.print(" that clients were likely to know.</p>\n");
+      this.writeSummaryPositive(out, relayIP, timestampStr);
     } else {
-      out.println("        <p>Result is NEGATIVE "
-          + "with high certainty!</p>\n");
-      out.println("        <p>We did not find any relay on IP address "
-          + relayIP
-          + " in the relay lists on or within a day of " + timestampStr
-          + ".</p>\n");
+      this.writeSummaryNegative(out, relayIP, timestampStr);
     }
 
     try {
@@ -598,7 +427,242 @@ public class ExoneraTorServlet extends HttpServlet {
           - requestedConnection) + " millis.");
     } catch (SQLException e) {
     }
-    writeFooter(out);
+    this.writeFooter(out);
+  }
+
+  /* Helper methods for writing the response. */
+
+  private void writeHeader(PrintWriter out) throws IOException {
+    out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 "
+          + "Transitional//EN\">\n"
+        + "<html>\n"
+        + "  <head>\n"
+        + "    <title>ExoneraTor</title>\n"
+        + "    <meta http-equiv=\"content-type\" content=\"text/html; "
+          + "charset=ISO-8859-1\">\n"
+        + "    <link href=\"/css/stylesheet-ltr.css\" type=\"text/css\" "
+          + "rel=\"stylesheet\">\n"
+        + "    <link href=\"/images/favicon.ico\" "
+          + "type=\"image/x-icon\" rel=\"shortcut icon\">\n"
+        + "  </head>\n"
+        + "  <body>\n"
+        + "    <div class=\"center\">\n"
+        + "      <div class=\"main-column\" style=\"margin:5; "
+          + "Padding:0;\">\n"
+        + "        <h2>ExoneraTor</h2>\n"
+        + "        <h3>or: a website that tells you whether a given IP "
+          + "address was a Tor relay</h3>\n"
+        + "        <br>\n"
+        + "        <p>Just because you see an Internet connection from a "
+          + "particular IP address does not mean you know <i>who</i> "
+          + "originated the traffic. Tor anonymizes Internet traffic by "
+          + "\"<a href=\"https://www.torproject.org/about/overview"
+          + "#thesolution\">onion routing</a>,\" sending packets "
+          + "through a series of encrypted hops before they reach their "
+          + "destination. Therefore, if you see traffic from a Tor node, "
+          + "you may be seeing traffic that originated from someone "
+          + "using Tor, rather than from the node operator itself. The "
+          + "Tor Project and Tor node operators have no records of the "
+          + "traffic that passes over the network, but we do maintain "
+          + "current and historical records of which IP addresses are "
+          + "part of the Tor network.</p>\n"
+        + "        <br>\n"
+        + "        <p>ExoneraTor tells you whether there was a Tor relay "
+          + "running on a given IP address at a given time. ExoneraTor "
+          + "learns these facts by parsing the public relay lists that "
+          + "are collected from the Tor directory authorities and the "
+          + "exit lists collected by TorDNSEL. By inputting an IP "
+          + "address and time, you can determine whether that IP was "
+          + "then a part of the Tor network.</p>\n"
+        + "        <br>\n"
+        + "        <p><font color=\"red\"><b>Notice:</b> Note that the "
+          + "information you are providing below may be visible to "
+          + "anyone who can read the network traffic between you and "
+          + "this web server or who has access to this web "
+          + "server.</font></p>\n"
+        + "        <br>\n");
+  }
+
+  private void writeUnableToConnectToDatabaseWarning(PrintWriter out)
+      throws IOException {
+    out.println("<p><font color=\"red\"><b>Warning: </b></font>Unable "
+        + "to connect to the database. If this problem persists, "
+        + "please <a href=\"mailto:tor-assistants at torproject.org\">let "
+        + "us know</a>!</p>\n");
+  }
+
+  private void writeNoDataWarning(PrintWriter out) throws IOException {
+    out.println("<p><font color=\"red\"><b>Warning: </b></font>This "
+        + "server doesn't have any relay lists available. If this "
+        + "problem persists, please "
+        + "<a href=\"mailto:tor-assistants at lists.torproject.org\">let "
+        + "us know</a>!</p>\n");
+  }
+
+  private void writeForm(PrintWriter out, String relayIP,
+      String ipWarning, String timestampStr, String timestampWarning)
+      throws IOException {
+    out.println("<a name=\"relay\"></a><h3>Was there a Tor relay running "
+        + "on this IP address?</h3>");
+    out.println("        <form action=\"#relay\">\n"
+        + "          <table>\n"
+        + "            <tr>\n"
+        + "              <td align=\"right\">IP address in question:"
+          + "</td>\n"
+        + "              <td><input type=\"text\" name=\"ip\" size=\"30\""
+          + (relayIP.length() > 0 ? " value=\"" + relayIP + "\""
+            : "")
+          + ">"
+          + (ipWarning.length() > 0 ? "<br><font color=\"red\">"
+          + ipWarning + "</font>" : "")
+        + "</td>\n"
+        + "              <td><i>(Ex.: 86.59.21.38 or "
+          + "2001:858:2:2:aabb:0:563b:1526)</i></td>\n"
+        + "            </tr>\n"
+        + "            <tr>\n"
+        + "              <td align=\"right\">Date:</td>\n"
+        + "              <td><input type=\"text\" name=\"timestamp\""
+          + " size=\"30\""
+          + (timestampStr.length() > 0 ? " value=\"" + timestampStr + "\""
+            : "")
+          + ">"
+          + (timestampWarning.length() > 0 ? "<br><font color=\"red\">"
+              + timestampWarning + "</font>" : "")
+        + "</td>\n"
+        + "              <td><i>(Ex.: 2010-01-01)"
+          + "</i></td>\n"
+        + "            </tr>\n"
+        + "            <tr>\n"
+        + "              <td></td>\n"
+        + "              <td>\n"
+        + "                <input type=\"submit\">\n"
+        + "                <input type=\"reset\">\n"
+        + "              </td>\n"
+        + "              <td></td>\n"
+        + "            </tr>\n"
+        + "          </table>\n"
+        + "        </form>\n");
+  }
+
+  private void writeSearchInfos(PrintWriter out, String relayIP,
+      String timestampStr) throws IOException {
+    out.printf("<p>Looking up IP address %s in the relay lists "
+        + "published ", relayIP);
+    out.printf("on or within a day of %s", timestampStr);
+    out.print(" as well as in the relevant exit lists. Clients could "
+        + "have selected any of these relays to build circuits. "
+        + "You may follow the links to relay lists and relay descriptors "
+        + "to grep for the lines printed below and confirm that results "
+        + "are correct.<br>\n");
+  }
+
+  private void writeNoDataForThisInterval(PrintWriter out, String relayIP,
+      String timestampStr) throws IOException {
+    out.println("        <p>No relay lists found!</p>\n"
+        + "        <p>Result is INDECISIVE!</p>\n"
+        + "        <p>We cannot make any statement whether there was "
+        + "a Tor relay running on IP address " + relayIP + " on "
+        + timestampStr + "! We "
+        + "did not find any relevant relay lists on or within a day of "
+        + "the given date. If "
+        + "you think this is an error on our side, please "
+        + "<a href=\"mailto:tor-assistants at torproject.org\">contact "
+        + "us</a>!</p>\n");
+  }
+
+  private void writeResultsTable(PrintWriter out,
+      List<String[]> tableRows) throws IOException {
+    out.print("<br>\n");
+    out.print("<table>\n");
+    out.print("<thead>\n");
+    out.print("<tr><th>Timestamp (UTC)</th><th>IP address(es)</th>"
+        + "<th>Identity fingerprint</th><th>Nickname</th><th>Exit</th>"
+        + "</tr>\n");
+    out.print("</thead>\n");
+    out.print("<tbody>\n");
+    for (String[] tableRow : tableRows) {
+      out.print("<tr>");
+      for (String tableColumn : tableRow) {
+        out.print("<td>" + tableColumn + "</td>");
+      }
+      out.print("</tr>\n");
+    }
+    out.print("</tbody>\n");
+    out.print("</table>\n");
+  }
+
+  private void writeNoneFound(PrintWriter out, String relayIP,
+      String timestampStr) throws IOException {
+    out.printf("        <p>None found!</p>\n"
+        + "        <p>Result is NEGATIVE with high certainty!</p>\n"
+        + "        <p>We did not find IP "
+        + "address " + relayIP + " in any of the relay or exit lists "
+        + "that were published on or within a day of %s.</p>\n",
+        timestampStr);
+  }
+
+  private void writeAddressesInSameNetwork(PrintWriter out,
+      String relayIP, String timestampStr,
+      List<String> addressesInSameNetwork) throws IOException {
+    out.printf("        <p>None found!</p>\n"
+        + "        <p>Result is NEGATIVE with high certainty!</p>\n"
+        + "        <p>We did not find IP "
+        + "address " + relayIP + " in any of the relay or exit lists "
+        + "that were published on or within a day of %s.</p>\n",
+        timestampStr);
+    if (!relayIP.contains(":")) {
+      out.print("        <p>The following other IP addresses of Tor "
+          + "relays in the same /24 network were found in relay "
+          + "and/or exit lists on or within a day of " + timestampStr
+          + " that could be related "
+          + "to IP address " + relayIP + ":</p>\n");
+    } else {
+      out.print("        <p>The following other IP addresses of Tor "
+          + "relays in the same /48 network were found in relay "
+          + "lists on or within a day of " + timestampStr
+          + " that could be related to IP "
+          + "address " + relayIP + ":</p>\n");
+    }
+    out.print("        <ul>\n");
+    for (String s : addressesInSameNetwork) {
+      out.print("        <li>" + s + "</li>\n");
+    }
+    out.print("        </ul>\n");
+  }
+
+  private void writeSummaryPositive(PrintWriter out, String relayIP,
+      String timestampStr) throws IOException {
+    out.print("        <p>Result is POSITIVE with high certainty!"
+        + "</p>\n"
+        + "        <p>We found one or more relays on IP address "
+        + relayIP + " in a ");
+    out.print("relay list published on or within a day of "
+        + timestampStr);
+    out.print(" that clients were likely to know.</p>\n");
+  }
+
+  private void writeSummaryNegative(PrintWriter out, String relayIP,
+      String timestampStr) throws IOException {
+    out.println("        <p>Result is NEGATIVE "
+        + "with high certainty!</p>\n");
+    out.println("        <p>We did not find any relay on IP address "
+        + relayIP
+        + " in the relay lists on or within a day of " + timestampStr
+        + ".</p>\n");
+  }
+
+  private void writeFooter(PrintWriter out) throws IOException {
+    out.println("        <br>\n"
+        + "      </div>\n"
+        + "    </div>\n"
+        + "    <div class=\"bottom\" id=\"bottom\">\n"
+        + "      <p>\"Tor\" and the \"Onion Logo\" are <a "
+          + "href=\"https://www.torproject.org/docs/trademark-faq.html.en"
+          + "\">registered trademarks</a> of The Tor Project, Inc.</p>\n"
+        + "    </div>\n"
+        + "  </body>\n"
+        + "</html>");
+    out.close();
   }
 }
 



More information about the tor-commits mailing list