commit 0eb47d2650b6edf516fc9ec1eb508c08db86ca46
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Wed May 16 17:00:46 2012 +0200
Add support for parsing v2 network statuses.
---
.../torproject/descriptor/RelayNetworkStatus.java | 68 ++++
.../descriptor/impl/BridgeNetworkStatusImpl.java | 2 +-
.../torproject/descriptor/impl/DescriptorImpl.java | 3 +
.../descriptor/impl/NetworkStatusImpl.java | 14 +-
.../impl/RelayNetworkStatusConsensusImpl.java | 2 +-
.../descriptor/impl/RelayNetworkStatusImpl.java | 360 ++++++++++++++++++++
.../impl/RelayNetworkStatusVoteImpl.java | 90 ++---
7 files changed, 475 insertions(+), 64 deletions(-)
diff --git a/src/org/torproject/descriptor/RelayNetworkStatus.java b/src/org/torproject/descriptor/RelayNetworkStatus.java
new file mode 100644
index 0000000..5d05f0c
--- /dev/null
+++ b/src/org/torproject/descriptor/RelayNetworkStatus.java
@@ -0,0 +1,68 @@
+/* Copyright 2012 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.descriptor;
+
+import java.util.List;
+import java.util.SortedMap;
+import java.util.SortedSet;
+
+/* Contains a v2 network status. */
+public interface RelayNetworkStatus extends Descriptor {
+
+ /* Return the network status version. */
+ public int getNetworkStatusVersion();
+
+ /* Return the authority's hostname. */
+ public String getHostname();
+
+ /* Return the authority's IP address. */
+ public String getAddress();
+
+ /* Return the authority's directory port. */
+ public int getDirport();
+
+ /* Return the directory's signing key's fingerprint. */
+ public String getFingerprint();
+
+ /* Return the contact line. */
+ public String getContactLine();
+
+ /* Return the directory signing key digest. */
+ public String getDirSigningKey();
+
+ /* Return recommended server versions or null if the status doesn't
+ * contain recommended server versions. */
+ public List<String> getRecommendedServerVersions();
+
+ /* Return recommended client versions or null if the status doesn't
+ * contain recommended client versions. */
+ public List<String> getRecommendedClientVersions();
+
+ /* Return the published time in milliseconds. */
+ public long getPublishedMillis();
+
+ /* Return the set of flags that this directory assigns to relays, or
+ * null if the status does not contain a dir-options line. */
+ public SortedSet<String> getDirOptions();
+
+ /* Return status entries, one for each contained relay. */
+ public SortedMap<String, NetworkStatusEntry> getStatusEntries();
+
+ /* Return whether a status entry with the given fingerprint exists. */
+ public boolean containsStatusEntry(String fingerprint);
+
+ /* Return a status entry by fingerprint or null if no such status entry
+ * exists. */
+ public NetworkStatusEntry getStatusEntry(String fingerprint);
+
+ /* Return the directory nickname. */
+ public String getNickname();
+
+ /* Return the directory signature. */
+ public String getDirectorySignature();
+
+ /* Return the status digest that the directory authority used to sign
+ * the network status. */
+ public String getStatusDigest();
+}
+
diff --git a/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java b/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
index 1d9818c..e6d1942 100644
--- a/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
+++ b/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
@@ -15,7 +15,7 @@ public class BridgeNetworkStatusImpl extends NetworkStatusImpl
protected BridgeNetworkStatusImpl(byte[] statusBytes,
String fileName, boolean failUnrecognizedDescriptorLines)
throws DescriptorParseException {
- super(statusBytes, failUnrecognizedDescriptorLines);
+ super(statusBytes, failUnrecognizedDescriptorLines, false);
this.setPublishedMillisFromFileName(fileName);
}
diff --git a/src/org/torproject/descriptor/impl/DescriptorImpl.java b/src/org/torproject/descriptor/impl/DescriptorImpl.java
index 6b1b167..7503419 100644
--- a/src/org/torproject/descriptor/impl/DescriptorImpl.java
+++ b/src/org/torproject/descriptor/impl/DescriptorImpl.java
@@ -66,6 +66,9 @@ public abstract class DescriptorImpl implements Descriptor {
} else if (firstLines.startsWith("ExitNode ")) {
parsedDescriptors.add(new ExitListImpl(rawDescriptorBytes, fileName,
failUnrecognizedDescriptorLines));
+ } else if (firstLines.startsWith("network-status-version 2\n")) {
+ parsedDescriptors.add(new RelayNetworkStatusImpl(rawDescriptorBytes,
+ failUnrecognizedDescriptorLines));
} else {
throw new DescriptorParseException("Could not detect descriptor "
+ "type in descriptor starting with '" + firstLines + "'.");
diff --git a/src/org/torproject/descriptor/impl/NetworkStatusImpl.java b/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
index d27e651..35e63b3 100644
--- a/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
+++ b/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
@@ -17,14 +17,14 @@ import org.torproject.descriptor.NetworkStatusEntry;
public abstract class NetworkStatusImpl extends DescriptorImpl {
protected NetworkStatusImpl(byte[] rawDescriptorBytes,
- boolean failUnrecognizedDescriptorLines)
- throws DescriptorParseException {
+ boolean failUnrecognizedDescriptorLines,
+ boolean containsDirSourceEntries) throws DescriptorParseException {
super(rawDescriptorBytes, failUnrecognizedDescriptorLines);
- this.splitAndParseParts(rawDescriptorBytes);
+ this.splitAndParseParts(rawDescriptorBytes, containsDirSourceEntries);
}
- private void splitAndParseParts(byte[] rawDescriptorBytes)
- throws DescriptorParseException {
+ private void splitAndParseParts(byte[] rawDescriptorBytes,
+ boolean containsDirSourceEntries) throws DescriptorParseException {
if (this.rawDescriptorBytes.length == 0) {
throw new DescriptorParseException("Descriptor is empty.");
}
@@ -34,8 +34,8 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
throw new DescriptorParseException("Empty lines are not allowed.");
}
int startIndex = 0;
- int firstDirSourceIndex = this.findFirstIndexOfKeyword(
- descriptorString, "dir-source");
+ int firstDirSourceIndex = !containsDirSourceEntries ? -1 :
+ this.findFirstIndexOfKeyword(descriptorString, "dir-source");
int firstRIndex = this.findFirstIndexOfKeyword(descriptorString, "r");
int directoryFooterIndex = this.findFirstIndexOfKeyword(
descriptorString, "directory-footer");
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
index 3d2af37..14082b8 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
@@ -41,7 +41,7 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
protected RelayNetworkStatusConsensusImpl(byte[] consensusBytes,
boolean failUnrecognizedDescriptorLines)
throws DescriptorParseException {
- super(consensusBytes, failUnrecognizedDescriptorLines);
+ super(consensusBytes, failUnrecognizedDescriptorLines, true);
Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList((
"vote-status,consensus-method,valid-after,fresh-until,"
+ "valid-until,voting-delay,known-flags").split(",")));
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
new file mode 100644
index 0000000..f3ab34a
--- /dev/null
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
@@ -0,0 +1,360 @@
+/* Copyright 2012 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.descriptor.impl;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.torproject.descriptor.RelayNetworkStatus;
+
+/* TODO Write unit tests. */
+
+public class RelayNetworkStatusImpl extends NetworkStatusImpl
+ implements RelayNetworkStatus {
+
+ protected static List<RelayNetworkStatus> parseStatuses(
+ byte[] statusesBytes, boolean failUnrecognizedDescriptorLines)
+ throws DescriptorParseException {
+ List<RelayNetworkStatus> parsedStatuses =
+ new ArrayList<RelayNetworkStatus>();
+ List<byte[]> splitStatusBytes =
+ DescriptorImpl.splitRawDescriptorBytes(statusesBytes,
+ "network-status-version 2");
+ for (byte[] statusBytes : splitStatusBytes) {
+ RelayNetworkStatus parsedStatus = new RelayNetworkStatusImpl(
+ statusBytes, failUnrecognizedDescriptorLines);
+ parsedStatuses.add(parsedStatus);
+ }
+ return parsedStatuses;
+ }
+
+ protected RelayNetworkStatusImpl(byte[] statusBytes,
+ boolean failUnrecognizedDescriptorLines)
+ throws DescriptorParseException {
+ super(statusBytes, failUnrecognizedDescriptorLines, false);
+ Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList((
+ "network-status-version,dir-source,fingerprint,contact,"
+ + "dir-signing-key,published").split(",")));
+ this.checkExactlyOnceKeywords(exactlyOnceKeywords);
+ Set<String> atMostOnceKeywords = new HashSet<String>(Arrays.asList(
+ "dir-options,client-versions,server-versions".split(",")));
+ this.checkAtMostOnceKeywords(atMostOnceKeywords);
+ this.checkFirstKeyword("network-status-version");
+ this.calculateDigest();
+ }
+
+ private void calculateDigest() throws DescriptorParseException {
+ try {
+ String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
+ String startToken = "network-status-version ";
+ String sigToken = "\ndirectory-signature ";
+ if (!ascii.contains(sigToken)) {
+ return;
+ }
+ int start = ascii.indexOf(startToken);
+ int sig = ascii.indexOf(sigToken) + sigToken.length();
+ sig = ascii.indexOf("\n", sig) + 1;
+ if (start >= 0 && sig >= 0 && sig > start) {
+ byte[] forDigest = new byte[sig - start];
+ System.arraycopy(this.getRawDescriptorBytes(), start,
+ forDigest, 0, sig - start);
+ this.statusDigest = DigestUtils.shaHex(forDigest);
+ }
+ } catch (UnsupportedEncodingException e) {
+ /* Handle below. */
+ }
+ if (this.statusDigest == null) {
+ throw new DescriptorParseException("Could not calculate status "
+ + "digest.");
+ }
+ }
+
+ protected void parseHeader(byte[] headerBytes)
+ throws DescriptorParseException {
+ Scanner s = new Scanner(new String(headerBytes)).useDelimiter("\n");
+ String nextCrypto = null;
+ StringBuilder crypto = null;
+ while (s.hasNext()) {
+ String line = s.next();
+ String[] parts = line.split(" ");
+ String keyword = parts[0];
+ if (keyword.equals("network-status-version")) {
+ this.parseNetworkStatusVersionLine(line, parts);
+ } else if (keyword.equals("dir-source")) {
+ this.parseDirSourceLine(line, parts);
+ } else if (keyword.equals("fingerprint")) {
+ this.parseFingerprintLine(line, parts);
+ } else if (keyword.equals("contact")) {
+ this.parseContactLine(line, parts);
+ } else if (keyword.equals("dir-signing-key")) {
+ this.parseDirSigningKeyLine(line, parts);
+ nextCrypto = "dir-signing-key";
+ } else if (keyword.equals("client-versions")) {
+ this.parseClientVersionsLine(line, parts);
+ } else if (keyword.equals("server-versions")) {
+ this.parseServerVersionsLine(line, parts);
+ } else if (keyword.equals("published")) {
+ this.parsePublishedLine(line, parts);
+ } else if (keyword.equals("dir-options")) {
+ this.parseDirOptionsLine(line, parts);
+ } else if (line.startsWith("-----BEGIN")) {
+ crypto = new StringBuilder();
+ crypto.append(line + "\n");
+ } else if (line.startsWith("-----END")) {
+ crypto.append(line + "\n");
+ String cryptoString = crypto.toString();
+ crypto = null;
+ if (nextCrypto.equals("dir-signing-key")) {
+ this.dirSigningKey = cryptoString;
+ } else {
+ throw new DescriptorParseException("Unrecognized crypto "
+ + "block in v2 network status.");
+ }
+ nextCrypto = null;
+ } else if (crypto != null) {
+ crypto.append(line + "\n");
+ } else if (this.failUnrecognizedDescriptorLines) {
+ throw new DescriptorParseException("Unrecognized line '" + line
+ + "' in v2 network status.");
+ } else {
+ if (this.unrecognizedLines == null) {
+ this.unrecognizedLines = new ArrayList<String>();
+ }
+ this.unrecognizedLines.add(line);
+ }
+ }
+ }
+
+ protected void parseFooter(byte[] footerBytes)
+ throws DescriptorParseException {
+ throw new DescriptorParseException("No directory footer expected in "
+ + "v2 network status.");
+ }
+
+ protected void parseDirectorySignature(byte[] directorySignatureBytes)
+ throws DescriptorParseException {
+ Scanner s = new Scanner(new String(directorySignatureBytes)).
+ useDelimiter("\n");
+ String nextCrypto = null;
+ StringBuilder crypto = null;
+ while (s.hasNext()) {
+ String line = s.next();
+ String[] parts = line.split(" ");
+ String keyword = parts[0];
+ if (keyword.equals("directory-signature")) {
+ this.parseDirectorySignatureLine(line, parts);
+ nextCrypto = "directory-signature";
+ } else if (line.startsWith("-----BEGIN")) {
+ crypto = new StringBuilder();
+ crypto.append(line + "\n");
+ } else if (line.startsWith("-----END")) {
+ crypto.append(line + "\n");
+ String cryptoString = crypto.toString();
+ crypto = null;
+ if (nextCrypto.equals("directory-signature")) {
+ this.directorySignature = cryptoString;
+ } else {
+ throw new DescriptorParseException("Unrecognized crypto "
+ + "block in v2 network status.");
+ }
+ nextCrypto = null;
+ } else if (crypto != null) {
+ crypto.append(line + "\n");
+ } else if (this.failUnrecognizedDescriptorLines) {
+ throw new DescriptorParseException("Unrecognized line '" + line
+ + "' in v2 network status.");
+ } else {
+ if (this.unrecognizedLines == null) {
+ this.unrecognizedLines = new ArrayList<String>();
+ }
+ this.unrecognizedLines.add(line);
+ }
+ }
+ }
+
+ private void parseNetworkStatusVersionLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (!line.equals("network-status-version 2")) {
+ throw new DescriptorParseException("Illegal network status version "
+ + "number in line '" + line + "'.");
+ }
+ this.networkStatusVersion = 2;
+ }
+
+ private void parseDirSourceLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length != 4) {
+ throw new DescriptorParseException("Illegal line '" + line
+ + "' in v2 network status.");
+ }
+ if (parts[1].length() < 1) {
+ throw new DescriptorParseException("Illegal hostname in '" + line
+ + "'.");
+ }
+ this.address = ParseHelper.parseIpv4Address(line, parts[2]);
+ this.dirPort = ParseHelper.parsePort(line, parts[3]);
+ }
+
+
+ private void parseFingerprintLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length != 2) {
+ throw new DescriptorParseException("Illegal line '" + line
+ + "' in v2 network status.");
+ }
+ this.fingerprint = ParseHelper.parseTwentyByteHexString(line,
+ parts[1]);
+ }
+
+ private void parseContactLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (line.length() > "contact ".length()) {
+ this.contactLine = line.substring("contact ".length());
+ } else {
+ this.contactLine = "";
+ }
+ }
+
+ private void parseDirSigningKeyLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (!line.equals("dir-signing-key")) {
+ throw new DescriptorParseException("Illegal line '" + line + "'.");
+ }
+ }
+
+ private void parseClientVersionsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.recommendedClientVersions = this.parseClientOrServerVersions(
+ line, parts);
+ }
+
+ private void parseServerVersionsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.recommendedServerVersions = this.parseClientOrServerVersions(
+ line, parts);
+ }
+
+ private List<String> parseClientOrServerVersions(String line,
+ String[] parts) throws DescriptorParseException {
+ List<String> result = new ArrayList<String>();
+ if (parts.length == 1) {
+ return result;
+ } else if (parts.length > 2) {
+ throw new DescriptorParseException("Illegal versions line '" + line
+ + "'.");
+ }
+ String[] versions = parts[1].split(",", -1);
+ for (int i = 0; i < versions.length; i++) {
+ String version = versions[i];
+ if (version.length() < 1) {
+ throw new DescriptorParseException("Illegal versions line '"
+ + line + "'.");
+ }
+ result.add(version);
+ }
+ return result;
+ }
+
+ private void parsePublishedLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, parts,
+ 1, 2);
+ }
+
+ private void parseDirOptionsLine(String line, String[] parts)
+ throws DescriptorParseException {
+ this.dirOptions = new TreeSet<String>();
+ for (int i = 1; i < parts.length; i++) {
+ this.dirOptions.add(parts[i]);
+ }
+ }
+
+ private void parseDirectorySignatureLine(String line, String[] parts)
+ throws DescriptorParseException {
+ if (parts.length < 2) {
+ throw new DescriptorParseException("Illegal line '" + line + "'.");
+ }
+ this.nickname = ParseHelper.parseNickname(line, parts[1]);
+ }
+
+ private String statusDigest;
+ public String getStatusDigest() {
+ return this.statusDigest;
+ }
+
+ private int networkStatusVersion;
+ public int getNetworkStatusVersion() {
+ return this.networkStatusVersion;
+ }
+
+ private String hostname;
+ public String getHostname() {
+ return this.hostname;
+ }
+
+ private String address;
+ public String getAddress() {
+ return this.address;
+ }
+
+ private int dirPort;
+ public int getDirport() {
+ return this.dirPort;
+ }
+
+ private String fingerprint;
+ public String getFingerprint() {
+ return this.fingerprint;
+ }
+
+ private String contactLine;
+ public String getContactLine() {
+ return this.contactLine;
+ }
+
+ private String dirSigningKey;
+ public String getDirSigningKey() {
+ return this.dirSigningKey;
+ }
+
+ private List<String> recommendedClientVersions;
+ public List<String> getRecommendedClientVersions() {
+ return this.recommendedClientVersions == null ? null :
+ new ArrayList<String>(this.recommendedClientVersions);
+ }
+
+ private List<String> recommendedServerVersions;
+ public List<String> getRecommendedServerVersions() {
+ return this.recommendedServerVersions == null ? null :
+ new ArrayList<String>(this.recommendedServerVersions);
+ }
+
+ private long publishedMillis;
+ public long getPublishedMillis() {
+ return this.publishedMillis;
+ }
+
+ private SortedSet<String> dirOptions;
+ public SortedSet<String> getDirOptions() {
+ return new TreeSet<String>(this.dirOptions);
+ }
+
+ private String nickname;
+ public String getNickname() {
+ return this.nickname;
+ }
+
+ private String directorySignature;
+ public String getDirectorySignature() {
+ return this.directorySignature;
+ }
+}
+
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
index 5791688..7cce313 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
@@ -39,7 +39,7 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
protected RelayNetworkStatusVoteImpl(byte[] voteBytes,
boolean failUnrecognizedDescriptorLines)
throws DescriptorParseException {
- super(voteBytes, failUnrecognizedDescriptorLines);
+ super(voteBytes, failUnrecognizedDescriptorLines, false);
Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList((
"vote-status,consensus-methods,published,valid-after,fresh-until,"
+ "valid-until,voting-delay,known-flags,dir-source,"
@@ -57,6 +57,7 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
protected void parseHeader(byte[] headerBytes)
throws DescriptorParseException {
Scanner s = new Scanner(new String(headerBytes)).useDelimiter("\n");
+ boolean skipCrypto = false; /* TODO Parse crypto parts. */
while (s.hasNext()) {
String line = s.next();
String[] parts = line.split(" ");
@@ -85,14 +86,40 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
this.parseKnownFlagsLine(line, parts);
} else if (keyword.equals("params")) {
this.parseParamsLine(line, parts);
- } else if (this.failUnrecognizedDescriptorLines) {
- throw new DescriptorParseException("Unrecognized line '" + line
- + "' in vote.");
- } else {
- if (this.unrecognizedLines == null) {
- this.unrecognizedLines = new ArrayList<String>();
+ } else if (keyword.equals("dir-source")) {
+ this.parseDirSourceLine(line, parts);
+ } else if (keyword.equals("contact")) {
+ this.parseContactLine(line, parts);
+ } else if (keyword.equals("dir-key-certificate-version")) {
+ this.parseDirKeyCertificateVersionLine(line, parts);
+ } else if (keyword.equals("dir-address")) {
+ this.parseDirAddressLine(line, parts);
+ } else if (keyword.equals("fingerprint")) {
+ this.parseFingerprintLine(line, parts);
+ } else if (keyword.equals("legacy-dir-key")) {
+ this.parseLegacyDirKeyLine(line, parts);
+ } else if (keyword.equals("dir-key-published")) {
+ this.parseDirKeyPublished(line, parts);
+ } else if (keyword.equals("dir-key-expires")) {
+ this.parseDirKeyExpiresLine(line, parts);
+ } else if (keyword.equals("dir-identity-key") ||
+ keyword.equals("dir-signing-key") ||
+ keyword.equals("dir-key-crosscert") ||
+ keyword.equals("dir-key-certification")) {
+ } else if (line.startsWith("-----BEGIN")) {
+ skipCrypto = true;
+ } else if (line.startsWith("-----END")) {
+ skipCrypto = false;
+ } else if (!skipCrypto) {
+ if (this.failUnrecognizedDescriptorLines) {
+ throw new DescriptorParseException("Unrecognized line '"
+ + line + "' in vote.");
+ } else {
+ if (this.unrecognizedLines == null) {
+ this.unrecognizedLines = new ArrayList<String>();
+ }
+ this.unrecognizedLines.add(line);
}
- this.unrecognizedLines.add(line);
}
}
}
@@ -225,53 +252,6 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
this.consensusParams = ParseHelper.parseKeyValuePairs(line, parts, 1);
}
- protected void parseDirSource(byte[] dirSourceBytes)
- throws DescriptorParseException {
- Scanner s = new Scanner(new String(dirSourceBytes)).
- useDelimiter("\n");
- boolean skipCrypto = false;
- while (s.hasNext()) {
- String line = s.next();
- String[] parts = line.split(" ");
- String keyword = parts[0];
- if (keyword.equals("dir-source")) {
- this.parseDirSourceLine(line, parts);
- } else if (keyword.equals("contact")) {
- this.parseContactLine(line, parts);
- } else if (keyword.equals("dir-key-certificate-version")) {
- this.parseDirKeyCertificateVersionLine(line, parts);
- } else if (keyword.equals("dir-address")) {
- this.parseDirAddressLine(line, parts);
- } else if (keyword.equals("fingerprint")) {
- this.parseFingerprintLine(line, parts);
- } else if (keyword.equals("legacy-dir-key")) {
- this.parseLegacyDirKeyLine(line, parts);
- } else if (keyword.equals("dir-key-published")) {
- this.parseDirKeyPublished(line, parts);
- } else if (keyword.equals("dir-key-expires")) {
- this.parseDirKeyExpiresLine(line, parts);
- } else if (keyword.equals("dir-identity-key") ||
- keyword.equals("dir-signing-key") ||
- keyword.equals("dir-key-crosscert") ||
- keyword.equals("dir-key-certification")) {
- } else if (line.startsWith("-----BEGIN")) {
- skipCrypto = true;
- } else if (line.startsWith("-----END")) {
- skipCrypto = false;
- } else if (!skipCrypto) {
- if (this.failUnrecognizedDescriptorLines) {
- throw new DescriptorParseException("Unrecognized line '"
- + line + "' in vote.");
- } else {
- if (this.unrecognizedLines == null) {
- this.unrecognizedLines = new ArrayList<String>();
- }
- this.unrecognizedLines.add(line);
- }
- }
- }
- }
-
private void parseDirSourceLine(String line, String[] parts)
throws DescriptorParseException {
if (parts.length != 7) {