[tor-commits] [metrics-web/master] Disable relay search and remove it from navigation.
karsten at torproject.org
karsten at torproject.org
Wed Jun 11 15:30:02 UTC 2014
commit 18d63dd7f414fb18940b254da8c3d6b5a7f54a95
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date: Wed Jun 11 17:22:11 2014 +0200
Disable relay search and remove it from navigation.
---
website/etc/web.xml | 11 -
.../org/torproject/metrics/web/StatusServlet.java | 24 -
.../metrics/web/status/RelaySearchServlet.java | 514 +-------------------
website/web/WEB-INF/banner.jsp | 10 -
website/web/WEB-INF/error.jsp | 4 -
website/web/WEB-INF/relay-search.jsp | 66 +--
6 files changed, 4 insertions(+), 625 deletions(-)
diff --git a/website/etc/web.xml b/website/etc/web.xml
index 519a9e6..a78cd28 100644
--- a/website/etc/web.xml
+++ b/website/etc/web.xml
@@ -138,17 +138,6 @@
</servlet-mapping>
<servlet>
- <servlet-name>Status</servlet-name>
- <servlet-class>
- org.torproject.metrics.web.StatusServlet
- </servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>Status</servlet-name>
- <url-pattern>/status.html</url-pattern>
- </servlet-mapping>
-
- <servlet>
<servlet-name>RelaySearch</servlet-name>
<servlet-class>
org.torproject.metrics.web.status.RelaySearchServlet
diff --git a/website/src/org/torproject/metrics/web/StatusServlet.java b/website/src/org/torproject/metrics/web/StatusServlet.java
deleted file mode 100644
index ec831df..0000000
--- a/website/src/org/torproject/metrics/web/StatusServlet.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Copyright 2011, 2012 The Tor Project
- * See LICENSE for licensing information */
-package org.torproject.metrics.web;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public class StatusServlet extends HttpServlet {
-
- private static final long serialVersionUID = -7249872082399236981L;
-
- public void doGet(HttpServletRequest request,
- HttpServletResponse response) throws IOException, ServletException {
-
- /* Forward the request to the JSP that does all the hard work. */
- request.getRequestDispatcher("WEB-INF/status.jsp").forward(request,
- response);
- }
-}
-
diff --git a/website/src/org/torproject/metrics/web/status/RelaySearchServlet.java b/website/src/org/torproject/metrics/web/status/RelaySearchServlet.java
index 49b091e..aac7f10 100644
--- a/website/src/org/torproject/metrics/web/status/RelaySearchServlet.java
+++ b/website/src/org/torproject/metrics/web/status/RelaySearchServlet.java
@@ -3,531 +3,21 @@
package org.torproject.metrics.web.status;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.TimeZone;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Pattern;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.sql.DataSource;
-import org.apache.commons.codec.binary.Base64;
-
-/**
- * Web page that allows users to search for relays in the descriptor
- * archives.
- *
- * Possible search terms for testing:
- * - gabelmoo
- * - gabelmoo 2010-09
- * - gabelmoo 2010-09-18
- * - gabelmoo $F2044413DAC2E02E3D6BCF4735A19BCA1DE97281
- * - gabelmoo 80.190.246
- * - gabelmoo $F2044413DAC2E02E3D6BCF4735A19BCA1DE97281 80.190.246
- * - 5898549205 dc737cc9dca16af6 79.212.74.45
- * - 5898549205 dc737cc9dca16af6
- * - 80.190.246.100
- * - $F2044413DAC2E02E3D6BCF4735A19BCA1DE97281
- * - $F2044413DAC2E02E3D6BCF4735A19BCA1DE97281 80.190.246
- * - 58985492
- * - 58985492 79.212.74.45
- */
public class RelaySearchServlet extends HttpServlet {
- private static final long serialVersionUID = -1772662230310611805L;
-
- private Pattern alphaNumDotDashDollarSpacePattern =
- Pattern.compile("[A-Za-z0-9\\.\\-$ ]+");
-
- private Pattern numPattern = Pattern.compile("[0-9]+");
-
- private Pattern hexPattern = Pattern.compile("[A-Fa-f0-9]+");
-
- private Pattern alphaNumPattern = Pattern.compile("[A-Za-z0-9]+");
-
- private SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");
-
- private SimpleDateFormat monthFormat = new SimpleDateFormat("yyyy-MM");
-
- private SimpleDateFormat dateTimeFormat =
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
- private long minValidAfterMillis;
-
- private DataSource ds;
-
- private Logger logger;
-
- public void init() {
-
- /* Initialize logger. */
- this.logger = Logger.getLogger(RelaySearchServlet.class.toString());
-
- /* Initialize date format parsers. */
- dayFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- monthFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
-
- /* Look up data source. */
- try {
- Context cxt = new InitialContext();
- this.ds = (DataSource) cxt.lookup("java:comp/env/jdbc/tordir");
- this.logger.info("Successfully looked up data source.");
- } catch (NamingException e) {
- this.logger.log(Level.WARNING, "Could not look up data source", e);
- }
-
- /* Look up first consensus in the database. */
- try {
- long requestedConnection = System.currentTimeMillis();
- Connection conn = this.ds.getConnection();
- String query = "SELECT MIN(validafter) AS first FROM consensus";
- Statement statement = conn.createStatement();
- ResultSet rs = statement.executeQuery(query);
- if (rs.next()) {
- this.minValidAfterMillis = rs.getTimestamp(1).getTime();
- }
- rs.close();
- statement.close();
- conn.close();
- this.logger.info("Returned a database connection to the pool "
- + "after " + (System.currentTimeMillis()
- - requestedConnection) + " millis.");
- } catch (SQLException e) {
- this.logger.log(Level.WARNING, "Could not look up first consensus "
- + "valid-after time in the database.", e);
- }
- }
+ private static final long serialVersionUID = -1772662230310611806L;
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException,
ServletException {
- /* Read search parameter. If we don't have a search parameter, we're
- * done here. */
- String searchParameter = request.getParameter("search");
- if (searchParameter == null || searchParameter.length() == 0) {
- request.getRequestDispatcher("WEB-INF/relay-search.jsp").forward(
- request, response);
- return;
- }
-
- /* Parse search parameter to identify what nickname, fingerprint,
- * and/or IP address to search for. A valid query contains no more
- * than one identifier for each of the fields. As a special case,
- * there are search terms consisting of 8 to 19 hex characters that
- * can be either a nickname or a fingerprint. */
- String searchNickname = "";
- String searchFingerprint = "";
- String searchIPAddress = "";
- SortedSet<String> searchDays = new TreeSet<String>();
- SortedSet<String> searchMonths = new TreeSet<String>();
- SortedSet<Long> searchDayTimestamps = new TreeSet<Long>();
- SortedSet<Long> searchMonthTimestamps = new TreeSet<Long>();
- boolean validQuery = false;
-
- /* Only parse search parameter if it contains nothing else than
- * alphanumeric characters, dots, and spaces. */
- if (alphaNumDotDashDollarSpacePattern.matcher(searchParameter).
- matches()) {
- SortedSet<String> searchTerms = new TreeSet<String>();
- if (searchParameter.trim().contains(" ")) {
- String[] split = searchParameter.trim().split(" ");
- for (int i = 0; i < split.length; i++) {
- if (split[i].length() > 0) {
- searchTerms.add(split[i]);
- }
- }
- } else {
- searchTerms.add(searchParameter.trim());
- }
-
- /* Parse each search term separately. */
- for (String searchTerm : searchTerms) {
-
- /* If the search term contains a dot, it can only be an IP
- * address. */
- if (searchTerm.contains(".") && !searchTerm.startsWith(".")) {
- String[] octets = searchTerm.split("\\.");
- if (searchIPAddress.length() > 0 || octets.length < 2 ||
- octets.length > 4) {
- validQuery = false;
- break;
- }
- boolean invalidOctet = false;
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < octets.length; i++) {
- if (!numPattern.matcher(octets[i]).matches() ||
- octets[i].length() > 3 ||
- Integer.parseInt(octets[i]) > 255) {
- invalidOctet = true;
- break;
- } else {
- sb.append("." + Integer.parseInt(octets[i]));
- }
- }
- if (invalidOctet) {
- validQuery = false;
- break;
- }
- if (octets.length < 4) {
- sb.append(".");
- }
- searchIPAddress = sb.toString().substring(1);
- validQuery = true;
- }
-
- /* If the search term contains hyphens, it must be a month or a
- * day. */
- else if (searchTerm.contains("-") &&
- searchTerm.startsWith("20")) {
- try {
- if (searchTerm.length() == 10) {
- searchDayTimestamps.add(dayFormat.parse(searchTerm).
- getTime());
- searchDays.add(searchTerm);
- } else if (searchTerm.length() == 7) {
- searchMonthTimestamps.add(monthFormat.parse(searchTerm).
- getTime());
- searchMonths.add(searchTerm);
- } else {
- validQuery = false;
- break;
- }
- } catch (ParseException e) {
- validQuery = false;
- break;
- }
- }
-
- /* If the search term starts with a $ followed by 8 to 40 hex
- * characters, it must be a fingerprint. */
- else if ((searchTerm.length() >= 9 && searchTerm.length() <= 41 &&
- searchTerm.startsWith("$") &&
- hexPattern.matcher(searchTerm.substring(1)).matches()) ||
- (searchTerm.length() > 19 && searchTerm.length() <= 40 &&
- !searchTerm.startsWith("$") &&
- hexPattern.matcher(searchTerm).matches())) {
- if (searchFingerprint.length() > 0) {
- validQuery = false;
- break;
- }
- searchFingerprint = searchTerm.substring(
- (searchTerm.startsWith("$") ? 1 : 0));
- validQuery = true;
- }
-
- /* If the search term contains up to 19 alphanumerical characters,
- * it must be a nickname. */
- else if (searchTerm.length() <= 19 &&
- alphaNumPattern.matcher(searchTerm).matches()) {
- if (searchNickname.length() > 0) {
- validQuery = false;
- break;
- }
- searchNickname = searchTerm;
- validQuery = true;
- }
-
- /* We didn't recognize this search term. */
- else {
- validQuery = false;
- break;
- }
- }
- }
-
- /* We only accept at most one month or three days, but not both, or
- * people could accidentally keep the database busy. */
- if (searchDays.size() > 3 || searchMonths.size() > 1 ||
- (searchMonths.size() == 1 && searchDays.size() > 0)) {
- validQuery = false;
- }
-
- /* If the query is invalid, stop here. */
- if (!validQuery) {
- request.setAttribute("invalidQuery", "Query is invalid.");
- request.getRequestDispatcher("WEB-INF/relay-search.jsp").
- forward(request, response);
- return;
- }
-
- /* Look up last consensus in the database. */
- long maxValidAfterMillis = -1L;
- try {
- long requestedConnection = System.currentTimeMillis();
- Connection conn = this.ds.getConnection();
- String query = "SELECT MAX(validafter) AS last FROM consensus";
- Statement statement = conn.createStatement();
- ResultSet rs = statement.executeQuery(query);
- if (rs.next()) {
- maxValidAfterMillis = rs.getTimestamp(1).getTime();
- }
- rs.close();
- statement.close();
- conn.close();
- this.logger.info("Returned a database connection to the pool "
- + "after " + (System.currentTimeMillis()
- - requestedConnection) + " millis.");
- } catch (SQLException e) {
- this.logger.log(Level.WARNING, "Could not look up last consensus "
- + "valid-after time in the database.", e);
- }
-
- /* Prepare a string that says what we're searching for. */
- List<String> recognizedSearchTerms = new ArrayList<String>();
- if (searchNickname.length() > 0) {
- recognizedSearchTerms.add("nickname <b>" + searchNickname + "</b>");
- }
- if (searchFingerprint.length() > 0) {
- recognizedSearchTerms.add("fingerprint <b>" + searchFingerprint
- + "</b>");
- }
- if (searchIPAddress.length() > 0) {
- recognizedSearchTerms.add("IP address <b>" + searchIPAddress
- + "</b>");
- }
- List<String> recognizedIntervals = new ArrayList<String>();
- for (String searchTerm : searchMonths) {
- recognizedIntervals.add("in <b>" + searchTerm + "</b>");
- }
- for (String searchTerm : searchDays) {
- recognizedIntervals.add("on <b>" + searchTerm + "</b>");
- }
- StringBuilder searchNoticeBuilder = new StringBuilder();
- if (maxValidAfterMillis > 0L) {
- searchNoticeBuilder.append("Most recent consensus in database is "
- + "from " + dateTimeFormat.format(maxValidAfterMillis)
- + ".</p><p>");
- }
- searchNoticeBuilder.append("Searching for relays with ");
- if (recognizedSearchTerms.size() == 1) {
- searchNoticeBuilder.append(recognizedSearchTerms.get(0));
- } else if (recognizedSearchTerms.size() == 2) {
- searchNoticeBuilder.append(recognizedSearchTerms.get(0) + " and "
- + recognizedSearchTerms.get(1));
- } else {
- for (int i = 0; i < recognizedSearchTerms.size() - 1; i++) {
- searchNoticeBuilder.append(recognizedSearchTerms.get(i) + ", ");
- }
- searchNoticeBuilder.append("and " + recognizedSearchTerms.get(
- recognizedSearchTerms.size() - 1));
- }
- if (recognizedIntervals.size() == 1) {
- searchNoticeBuilder.append(" running "
- + recognizedIntervals.get(0));
- } else if (recognizedIntervals.size() == 2) {
- searchNoticeBuilder.append(" running " + recognizedIntervals.get(0)
- + " and/or " + recognizedIntervals.get(1));
- } else if (recognizedIntervals.size() > 2) {
- searchNoticeBuilder.append(" running ");
- for (int i = 0; i < recognizedIntervals.size() - 1; i++) {
- searchNoticeBuilder.append(recognizedIntervals.get(i) + ", ");
- }
- searchNoticeBuilder.append("and/or " + recognizedIntervals.get(
- recognizedIntervals.size() - 1));
- }
- searchNoticeBuilder.append(" ...");
- String searchNotice = searchNoticeBuilder.toString();
- request.setAttribute("searchNotice", searchNotice);
-
- /* Prepare the query string. */
- StringBuilder conditionBuilder = new StringBuilder();
- boolean addAnd = false;
- if (searchNickname.length() > 0) {
- conditionBuilder.append((addAnd ? "AND " : "")
- + "LOWER(nickname) LIKE '" + searchNickname.toLowerCase()
- + "%' ");
- addAnd = true;
- }
- if (searchFingerprint.length() > 0) {
- conditionBuilder.append((addAnd ? "AND " : "")
- + "fingerprint LIKE '" + searchFingerprint.toLowerCase()
- + "%' ");
- addAnd = true;
- }
- if (searchIPAddress.length() > 0) {
- conditionBuilder.append((addAnd ? "AND " : "")
- + "address LIKE '" + searchIPAddress + "%' ");
- addAnd = true;
- }
- List<String> timeIntervals = new ArrayList<String>();
- if (searchDayTimestamps.size() > 0 ||
- searchMonthTimestamps.size() > 0) {
- StringBuilder timeIntervalBuilder = new StringBuilder();
- boolean addOr = false;
- timeIntervalBuilder.append("AND (");
- for (long searchTimestamp : searchDayTimestamps) {
- if (searchTimestamp < this.minValidAfterMillis) {
- request.setAttribute("outsideInterval", "Returned search "
- + "results may be incomplete, as our data only dates back "
- + "to " + dateTimeFormat.format(this.minValidAfterMillis)
- + ". Older archives are not available.");
- }
- timeIntervalBuilder.append((addOr ? "OR " : "")
- + "(validafter >= '"
- + dateTimeFormat.format(searchTimestamp) + "' AND "
- + "validafter < '" + dateTimeFormat.format(searchTimestamp
- + 24L * 60L * 60L * 1000L) + "') ");
- addOr = true;
- }
- for (long searchTimestamp : searchMonthTimestamps) {
- if (searchTimestamp < this.minValidAfterMillis) {
- request.setAttribute("outsideInterval", "Returned search "
- + "results may be incomplete, as our data only dates back "
- + "to " + dateTimeFormat.format(this.minValidAfterMillis)
- + ". Older archives are not available.");
- }
- Calendar firstOfNextMonth = Calendar.getInstance(
- TimeZone.getTimeZone("UTC"));
- firstOfNextMonth.setTimeInMillis(searchTimestamp);
- firstOfNextMonth.add(Calendar.MONTH, 1);
- timeIntervalBuilder.append((addOr ? "OR " : "")
- + "(validafter >= '"
- + dateTimeFormat.format(searchTimestamp) + "' AND "
- + "validafter < '" + dateTimeFormat.format(
- firstOfNextMonth.getTimeInMillis()) + "') ");
- addOr = true;
- }
- timeIntervalBuilder.append(") ");
- timeIntervals.add(timeIntervalBuilder.toString());
- } else {
- timeIntervals.add("AND validafter >= '"
- + dateTimeFormat.format(System.currentTimeMillis()
- - 4L * 24L * 60L * 60L * 1000L) + "' ");
- timeIntervals.add("AND validafter >= '"
- + dateTimeFormat.format(System.currentTimeMillis()
- - 30L * 24L * 60L * 60L * 1000L) + "' ");
- }
- List<String> queries = new ArrayList<String>();
- for (String timeInterval : timeIntervals) {
- StringBuilder queryBuilder = new StringBuilder();
- queryBuilder.append("SELECT validafter, fingerprint, descriptor, "
- + "rawdesc FROM statusentry WHERE validafter IN (SELECT "
- + "validafter FROM statusentry WHERE ");
- queryBuilder.append(conditionBuilder.toString());
- queryBuilder.append(timeInterval);
- queryBuilder.append("ORDER BY validafter DESC LIMIT 31) AND ");
- queryBuilder.append(conditionBuilder.toString());
- queryBuilder.append(timeInterval);
- queries.add(queryBuilder.toString());
- }
-
- /* Actually execute the query. */
- long startedQuery = System.currentTimeMillis();
- SortedMap<String, SortedSet<String>> foundDescriptors =
- new TreeMap<String, SortedSet<String>>(
- Collections.reverseOrder());
- Map<String, String> rawValidAfterLines =
- new HashMap<String, String>();
- Map<String, String> rawStatusEntries = new HashMap<String, String>();
- String query = null;
- int matches = 0;
- try {
- long requestedConnection = System.currentTimeMillis();
- Connection conn = this.ds.getConnection();
- while (!queries.isEmpty()) {
- query = queries.remove(0);
- this.logger.info("Running query '" + query + "'.");
- Statement statement = conn.createStatement();
- ResultSet rs = statement.executeQuery(query);
- while (rs.next()) {
- matches++;
- String validAfter = rs.getTimestamp(1).toString().
- substring(0, 19);
- String fingerprint = rs.getString(2);
- if (!foundDescriptors.containsKey(validAfter)) {
- foundDescriptors.put(validAfter, new TreeSet<String>());
- }
- foundDescriptors.get(validAfter).add(validAfter + " "
- + fingerprint);
- if (!rawValidAfterLines.containsKey(validAfter)) {
- rawValidAfterLines.put(validAfter, "<tt>valid-after "
- + "<a href=\"https://exonerator.torproject.org/"
- + "consensus?valid-after="
- + validAfter.replaceAll(":", "-").replaceAll(" ", "-")
- + "\" target=\"_blank\">" + validAfter + "</a></tt><br>");
- }
- byte[] rawStatusEntry = rs.getBytes(4);
- String statusEntryLines = null;
- try {
- statusEntryLines = new String(rawStatusEntry, "US-ASCII");
- } catch (UnsupportedEncodingException e) {
- /* This shouldn't happen, because we know that ASCII is
- * supported. */
- }
- StringBuilder rawStatusEntryBuilder = new StringBuilder();
- String[] lines = statusEntryLines.split("\n");
- for (String line : lines) {
- if (line.startsWith("r ")) {
- String[] parts = line.split(" ");
- String descriptorBase64 = String.format("%040x",
- new BigInteger(1, Base64.decodeBase64(parts[3]
- + "==")));
- rawStatusEntryBuilder.append("<tt>r " + parts[1] + " "
- + parts[2] + " <a href=\""
- + "https://exonerator.torproject.org/"
- + "serverdesc?desc-id="
- + descriptorBase64 + "\" target=\"_blank\">" + parts[3]
- + "</a> " + parts[4] + " " + parts[5] + " " + parts[6]
- + " " + parts[7] + " " + parts[8] + "</tt><br>");
- } else {
- rawStatusEntryBuilder.append("<tt>" + line + "</tt><br>");
- }
- }
- rawStatusEntries.put(validAfter + " " + fingerprint,
- rawStatusEntryBuilder.toString());
- }
- rs.close();
- statement.close();
- if (matches >= 31) {
- queries.clear();
- }
- }
- conn.close();
- this.logger.info("Returned a database connection to the pool "
- + "after " + (System.currentTimeMillis()
- - requestedConnection) + " millis.");
- } catch (SQLException e) {
-
- /* Tell the user we have a database problem. */
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
- "Database problem");
- return;
- }
- request.setAttribute("query", query);
- request.setAttribute("queryTime", System.currentTimeMillis()
- - startedQuery);
- request.setAttribute("foundDescriptors", foundDescriptors);
- request.setAttribute("rawValidAfterLines", rawValidAfterLines);
- request.setAttribute("rawStatusEntries", rawStatusEntries);
- request.setAttribute("matches", matches);
-
- /* We're done. Let the JSP do the rest. */
+ /* Let the JSP display that we're out of service. */
request.getRequestDispatcher("WEB-INF/relay-search.jsp").forward(
request, response);
}
diff --git a/website/web/WEB-INF/banner.jsp b/website/web/WEB-INF/banner.jsp
index 5f6a43f..3acea7f 100644
--- a/website/web/WEB-INF/banner.jsp
+++ b/website/web/WEB-INF/banner.jsp
@@ -12,8 +12,6 @@
%>class="current"<%} else {%>href="/graphs.html"<%}%>>Graphs</a>
<a <% if (currentPage.endsWith("research.jsp")) {
%>class="current"<%} else {%>href="/research.html"<%}%>>Research</a>
- <a <% if (currentPage.endsWith("status.jsp")) {
- %>class="current"<%} else {%>href="/status.html"<%}%>>Status</a>
<%if (currentPage.endsWith("graphs.jsp") ||
currentPage.endsWith("network.jsp") ||
currentPage.endsWith("bubbles.jsp") ||
@@ -34,14 +32,6 @@
%>class="current"<%} else {%>href="/performance.html"<%}
%>>Performance</a>
</font>
- <%} else if (currentPage.endsWith("status.jsp") ||
- currentPage.endsWith("relay-search.jsp")) {
- %><br>
- <font size="2">
- <a <%if (currentPage.endsWith("relay-search.jsp")){
- %>class="current"<%} else {%>href="/relay-search.html"<%}
- %>>Relay Search</a>
- </font>
<%} else if (currentPage.endsWith("research.jsp") ||
currentPage.endsWith("data.jsp") ||
currentPage.endsWith("formats.jsp") ||
diff --git a/website/web/WEB-INF/error.jsp b/website/web/WEB-INF/error.jsp
index 1626035..17ddee3 100644
--- a/website/web/WEB-INF/error.jsp
+++ b/website/web/WEB-INF/error.jsp
@@ -55,10 +55,6 @@ Maybe you find what you're looking for on our sitemap:
<li><a href="tools.html">Tools</a></li>
<li><a href="stats.html">Statistics</a></li>
</ul></li>
-<li><a href="status.html">Status</a>
-<ul>
-<li><a href="relay-search.html">Relay Search</a></li>
-</ul></li>
</ul>
</p>
diff --git a/website/web/WEB-INF/relay-search.jsp b/website/web/WEB-INF/relay-search.jsp
index e6eb630..90b7512 100644
--- a/website/web/WEB-INF/relay-search.jsp
+++ b/website/web/WEB-INF/relay-search.jsp
@@ -13,73 +13,11 @@
<%@ include file="banner.jsp"%>
<div class="main-column">
<h2>Tor Metrics Portal: Relay Search</h2>
- <p><font color="red"><b>Notice:</b> This service will be shut down
- after June 10, 2014. Possible alternatives are
+ <p><font color="red">Sorry, this service has been shut down
+ on June 10, 2014. Possible alternatives are
<a href="https://atlas.torproject.org">Atlas</a> and
<a href="https://globe.torproject.org">Globe</a>.
</font></p>
- <p>Search for a relay in the relay descriptor archive by typing
- (part of) a <b>nickname</b>, <b>$-prefixed fingerprint</b>, or <b>IP
- address</b> and optionally a <b>month (yyyy-mm)</b> or up to three
- <b>days (yyyy-mm-dd)</b> in the following search field and
- clicking Search. The search will stop after 30 hits or, unless you
- provide a month or a day, after parsing the last 30 days of relay
- lists.</p>
- <br>
- <form action="relay-search.html">
- <table>
- <tr>
- <td><input type="text" name="search"
- value="<c:out value="${param.search}"/>"></td>
- <td><input type="submit" value="Search"></td>
- </tr>
- </table>
- </form>
- <br>
- <c:if test="${not empty invalidQuery}">
- <p>Sorry, I didn't understand your query. Please provide a
- nickname (e.g., "gabelmoo"), at least the first 8 hex characters
- of a fingerprint prefixed by $ (e.g., "$F2044413"), or at least
- the first two octets of an IPv4 address in dotted-decimal notation
- (e.g., "80.190"). You can also provide at most three months or
- days in ISO 8601 format (e.g., "2010-09" or "2010-09-17").</p>
- </c:if>
- <c:if test="${not empty outsideInterval}">
- <p>${outsideInterval}</p>
- </c:if>
- <c:if test="${not empty searchNotice}">
- <p>${searchNotice}</p>
- </c:if>
- <c:if test="${not empty query}">
- <!-- ${query} -->
- </c:if>
- <c:if test="${not empty queryTime}">
- <c:forEach var="consensus" items="${foundDescriptors}">
- ${rawValidAfterLines[consensus.key]}
- <c:forEach var="statusentry" items="${consensus.value}">
- ${rawStatusEntries[statusentry]}
- </c:forEach>
- <br>
- </c:forEach>
- <p>Found
- <c:choose>
- <c:when test="${matches > 30}">
- more than 30 relays (displaying only those in the last
- consensuses)
- </c:when>
- <c:otherwise>
- ${matches} relays
- </c:otherwise>
- </c:choose>
- in <fmt:formatNumber value="${queryTime / 1000}" pattern="#.###"/>
- seconds.</p>
- <c:if test="${queryTime > 10000}">
- <p>In theory, search time should not exceed 10 seconds. The
- query was '${query}'. If this or similar searches remain slow,
- please <a href="mailto:tor-assistants at torproject.org">let us
- know</a>!</p>
- </c:if>
- </c:if>
</div>
</div>
<div class="bottom" id="bottom">
More information about the tor-commits
mailing list