tor-commits
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
May 2012
- 20 participants
- 844 discussions

[onionoo/master] Changes were not deployed on April 3, but today.
by karsten@torproject.org 14 May '12
by karsten@torproject.org 14 May '12
14 May '12
commit c3ae92000c8cd9324b8020ecd4610c3aab228716
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon May 14 14:55:52 2012 +0200
Changes were not deployed on April 3, but today.
---
web/index.html | 34 +++++++++++++++++-----------------
1 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/web/index.html b/web/index.html
index 7a73591..3b15077 100755
--- a/web/index.html
+++ b/web/index.html
@@ -85,8 +85,8 @@ Required field.</li>
document.
The method and its parameters determines which relay and/or bridge
summaries are included in the response.
-<font color="red">These methods have been deprecated on April 3, 2012 and
-will be removed after June 3, 2012.
+<font color="red">These methods have been deprecated on May 14, 2012 and
+will be removed after July 14, 2012.
See the Methods section at the end of this page.</font>
</p>
<table border="0" cellpadding="4" cellspacing="0" summary="">
@@ -242,7 +242,7 @@ assigned to this relay by the directory authorities.
The unit is arbitrary; currently it's kilobytes per second, but that might
change in the future.
Required field.
-Added on April 3, 2012.</li>
+Added on May 14, 2012.</li>
<li><b>"last_restarted":</b> UTC timestamp (YYYY-MM-DD hh:mm:ss) when the
relay was last (re-)started.
<font color="red">Optional field.</font>
@@ -327,8 +327,8 @@ Optional field.</li>
document.
The method and its parameters determines which relay and/or bridge
details are included in the response.
-<font color="red">These methods have been deprecated on April 3, 2012 and
-will be removed after June 3, 2012.
+<font color="red">These methods have been deprecated on May 14, 2012 and
+will be removed after July 14, 2012.
See the Methods section at the end of this page.</font>
</p>
<table border="0" cellpadding="4" cellspacing="0" summary="">
@@ -491,8 +491,8 @@ The specification of bandwidth history objects is similar to those in the
<p>The following methods are available that all return a single document.
The method and its parameters determines which relay and/or bridge
bandwidth documents are included in the response.
-<font color="red">These methods have been deprecated on April 3, 2012 and
-will be removed after June 3, 2012.
+<font color="red">These methods have been deprecated on May 14, 2012 and
+will be removed after July 14, 2012.
See the Methods section at the end of this page.</font>
</p>
<table border="0" cellpadding="4" cellspacing="0" summary="">
@@ -574,21 +574,21 @@ more relay and/or bridge documents.</p>
<td><b>GET summary</b></td>
<td>Return summaries of all relays and bridges that are currently running
or that have been running in the past week.
-<font color="blue">Method added on April 3, 2012.</font>
+<font color="blue">Method added on May 14, 2012.</font>
</td>
</tr>
<tr>
<td><b>GET details</b></td>
<td>Return details of all relays and bridges that are currently running
or that have been running in the past week.
-<font color="blue">Method added on April 3, 2012.</font>
+<font color="blue">Method added on May 14, 2012.</font>
</td>
</tr>
<tr>
<td><b>GET bandwidth</b></td>
<td>Return bandwidth documents of all relays and bridges that are
currently running or that have been running in the past week.
-<font color="blue">Method added on April 3, 2012.</font>
+<font color="blue">Method added on May 14, 2012.</font>
</td>
</tr>
</table>
@@ -602,12 +602,12 @@ of relay and/or bridge documents to be included in the response.</p>
<tr><td><b>type</b></td><td>Return only relay (parameter value
<b>relay</b>) or only bridge documents (parameter value
<b>bridge</b>).
-<font color="blue">Parameter added on April 3, 2012.</font>
+<font color="blue">Parameter added on May 14, 2012.</font>
</td></tr>
<tr><td><b>running</b></td><td>Return only running (parameter value
<b>true</b>) or only non-running relays and/or bridges (paramter value
<b>false</b>).
-<font color="blue">Parameter added on April 3, 2012.</font>
+<font color="blue">Parameter added on May 14, 2012.</font>
</td></tr>
<tr><td><b>search</b></td><td>Return only relays with the parameter value
matching the beginning of a nickname, (possibly $-prefixed) fingerprint,
@@ -617,7 +617,7 @@ Searches are case-insensitive.
Full fingerprints should always be hashed using SHA-1, regardless of
searching for a relay or a bridge, in order to not accidentally leak
non-hashed bridge fingerprints in the URL.
-<font color="blue">Parameter added on April 3, 2012.</font>
+<font color="blue">Parameter added on May 14, 2012.</font>
</td></tr>
<tr><td><b>lookup</b></td><td>Return only the relay with the parameter
value matching the fingerprint or the bridge with the parameter value
@@ -625,7 +625,7 @@ matching the hashed fingerprint.
Fingerprints should always be hashed using SHA-1, regardless of looking up
a relay or a bridge, in order to not accidentally leak non-hashed bridge
fingerprints in the URL.
-<font color="blue">Parameter added on April 3, 2012.</font>
+<font color="blue">Parameter added on May 14, 2012.</font>
</td></tr>
</table>
<p>Relay and/or bridge documents in the response can be ordered and
@@ -646,17 +646,17 @@ Relays which don't have any value for a field to be ordered by are always
appended to the end, regardless or sorting order.
If no <b>order</b> parameter is given, ordering of results is
undefined.
-<font color="blue">Parameter added on April 3, 2012.</font>
+<font color="blue">Parameter added on May 14, 2012.</font>
</td></tr>
<tr><td><b>offset</b></td><td>Skip the given number of relays and/or
bridges.
-<font color="blue">Parameter added on April 3, 2012.</font>
+<font color="blue">Parameter added on May 14, 2012.</font>
</td></tr>
<tr><td><b>limit</b></td><td>Limit result to the given number of
relays and/or bridges.
When used together with <b>offset</b>, the offsetting step precedes the
limiting step.
-<font color="blue">Parameter added on April 3, 2012.</font>
+<font color="blue">Parameter added on May 14, 2012.</font>
</td></tr>
</table>
</body>
1
0

[onionoo/master] Add parameters for filtering and sorting results.
by karsten@torproject.org 14 May '12
by karsten@torproject.org 14 May '12
14 May '12
commit d7f391663ba31daef6ced853d944d92dffd13049
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Apr 3 19:23:30 2012 +0200
Add parameters for filtering and sorting results.
Parameters are more flexible than our current URLs. Current functionality
can be implemented with the type, running, search, and lookup parameters.
The order and limit parameters can be used, e.g., for top-10 lists of
relays by bandwidth. The offset parameter might be useful for paged
results.
This is a major API change, so we're leaving the deprecated methods in for
two months instead of one.
---
src/org/torproject/onionoo/DetailDataWriter.java | 29 ++
src/org/torproject/onionoo/ResourceServlet.java | 526 ++++++++++++++--------
web/index.html | 206 ++++++++-
3 files changed, 555 insertions(+), 206 deletions(-)
diff --git a/src/org/torproject/onionoo/DetailDataWriter.java b/src/org/torproject/onionoo/DetailDataWriter.java
index 90c2160..cfae5ff 100644
--- a/src/org/torproject/onionoo/DetailDataWriter.java
+++ b/src/org/torproject/onionoo/DetailDataWriter.java
@@ -211,6 +211,8 @@ public class DetailDataWriter {
SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Map<String, Long> relaysByConsensusWeight =
+ new HashMap<String, Long>();
for (Map.Entry<String, Node> relay : this.relays.entrySet()) {
String fingerprint = relay.getKey();
@@ -414,6 +416,33 @@ public class DetailDataWriter {
+ "broken. Ignoring.");
e.printStackTrace();
}
+
+ /* Remember consensus weight to facilitate ordering of results in
+ * the servlet. */
+ relaysByConsensusWeight.put(fingerprint, consensusWeight);
+ }
+
+ /* Write consensus weights to disk to facilitate ordering of results
+ * in the servlet. */
+ File relaysByConsensusWeightFile =
+ new File("out/relays-by-consensus-weight.csv");
+ try {
+ relaysByConsensusWeightFile.getParentFile().mkdirs();
+ BufferedWriter bw = new BufferedWriter(new FileWriter(
+ relaysByConsensusWeightFile));
+ for (Map.Entry<String, Long> e :
+ relaysByConsensusWeight.entrySet()) {
+ String fingerprint = e.getKey();
+ long consensusWeight = e.getValue();
+ bw.write(fingerprint + "," + String.valueOf(consensusWeight)
+ + "\n");
+ }
+ bw.close();
+ } catch (IOException e) {
+ System.err.println("Could not write file '"
+ + relaysByConsensusWeightFile.getAbsolutePath() + "'. "
+ + "Ordering by consensus_weight may now be broken. Ignoring.");
+ e.printStackTrace();
}
/* Return the files that we didn't update. */
diff --git a/src/org/torproject/onionoo/ResourceServlet.java b/src/org/torproject/onionoo/ResourceServlet.java
index 4149375..a85f3ec 100644
--- a/src/org/torproject/onionoo/ResourceServlet.java
+++ b/src/org/torproject/onionoo/ResourceServlet.java
@@ -8,6 +8,8 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -41,7 +43,8 @@ public class ResourceServlet extends HttpServlet {
boolean readSummaryFile = false;
private String relaysPublishedLine = null, bridgesPublishedLine = null;
private List<String> relayLines = new ArrayList<String>(),
- bridgeLines = new ArrayList<String>();
+ bridgeLines = new ArrayList<String>(),
+ relaysByConsensusWeight = new ArrayList<String>();
private Map<String, String>
relayFingerprintSummaryLines = new HashMap<String, String>(),
bridgeFingerprintSummaryLines = new HashMap<String, String>();
@@ -107,6 +110,44 @@ public class ResourceServlet extends HttpServlet {
} catch (DecoderException e) {
return;
}
+ List<String> orderRelaysByConsensusWeight = new ArrayList<String>();
+ File relaysByConsensusWeightFile =
+ new File(this.outDirString + "/relays-by-consensus-weight.csv");
+ if (relaysByConsensusWeightFile.exists()) {
+ try {
+ BufferedReader br = new BufferedReader(new FileReader(
+ relaysByConsensusWeightFile));
+ String line;
+ while ((line = br.readLine()) != null) {
+ String[] parts = line.split(",");
+ if (parts.length != 2) {
+ return;
+ }
+ long consensusWeight = Long.parseLong(parts[1]);
+ String fingerprint = parts[0];
+ orderRelaysByConsensusWeight.add(
+ String.format("%020d %s", consensusWeight, fingerprint));
+ String hashedFingerprint = DigestUtils.shaHex(
+ Hex.decodeHex(fingerprint.toCharArray())).
+ toUpperCase();
+ orderRelaysByConsensusWeight.add(
+ String.format("%020d %s", consensusWeight,
+ hashedFingerprint));
+ }
+ br.close();
+ Collections.sort(orderRelaysByConsensusWeight);
+ this.relaysByConsensusWeight = new ArrayList<String>();
+ for (String relay : orderRelaysByConsensusWeight) {
+ this.relaysByConsensusWeight.add(relay.split(" ")[1]);
+ }
+ } catch (IOException e) {
+ return;
+ } catch (NumberFormatException e) {
+ return;
+ } catch (DecoderException e) {
+ return;
+ }
+ }
}
this.summaryFileLastModified = summaryFile.lastModified();
this.readSummaryFile = true;
@@ -131,85 +172,237 @@ public class ResourceServlet extends HttpServlet {
uri = uri.substring("/onionoo".length());
}
String resourceType = null;
+ boolean isOldStyleUri = false;
if (uri.startsWith("/summary/")) {
resourceType = "summary";
+ isOldStyleUri = true;
} else if (uri.startsWith("/details/")) {
resourceType = "details";
+ isOldStyleUri = true;
} else if (uri.startsWith("/bandwidth/")) {
resourceType = "bandwidth";
+ isOldStyleUri = true;
+ } else if (uri.startsWith("/summary")) {
+ resourceType = "summary";
+ } else if (uri.startsWith("/details")) {
+ resourceType = "details";
+ } else if (uri.startsWith("/bandwidth")) {
+ resourceType = "bandwidth";
} else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- /* Handle any errors resulting from invalid requests. */
- if (uri.equals("/" + resourceType + "/all")) {
- } else if (uri.equals("/" + resourceType + "/running")) {
- } else if (uri.equals("/" + resourceType + "/relays")) {
- } else if (uri.equals("/" + resourceType + "/bridges")) {
- } else if (uri.startsWith("/" + resourceType + "/search/")) {
- String searchParameter = this.parseSearchParameter(uri.substring(
- ("/" + resourceType + "/search/").length()));
- if (searchParameter == null) {
+ /* Extract parameters either from the old-style URI or from request
+ * parameters. */
+ Map<String, String> parameterMap;
+ if (isOldStyleUri) {
+ parameterMap = this.getParameterMapForOldStyleUri(uri,
+ resourceType);
+ if (parameterMap == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
- } else if (uri.startsWith("/" + resourceType + "/lookup/")) {
- Set<String> fingerprintParameters = this.parseFingerprintParameters(
- uri.substring(("/" + resourceType + "/lookup/").length()));
- if (fingerprintParameters == null) {
+ } else {
+ parameterMap = new HashMap<String, String>();
+ for (Object parameterKey : request.getParameterMap().keySet()) {
+ String[] parameterValues =
+ request.getParameterValues((String) parameterKey);
+ parameterMap.put((String) parameterKey, parameterValues[0]);
+ }
+ }
+
+ /* Make sure that the request doesn't contain any unknown
+ * parameters. */
+ Set<String> knownParameters = new HashSet<String>(Arrays.asList(
+ "type,running,search,lookup,order,limit,offset".split(",")));
+ for (String parameterKey : parameterMap.keySet()) {
+ if (!knownParameters.contains(parameterKey)) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ }
+
+ /* Filter relays and bridges matching the request. */
+ Map<String, String> filteredRelays = new HashMap<String, String>(
+ this.relayFingerprintSummaryLines);
+ Map<String, String> filteredBridges = new HashMap<String, String>(
+ this.bridgeFingerprintSummaryLines);
+ if (parameterMap.containsKey("type")) {
+ String typeParameterValue = parameterMap.get("type");
+ boolean relaysRequested = true;
+ if (typeParameterValue.equals("bridge")) {
+ relaysRequested = false;
+ } else if (!typeParameterValue.equals("relay")) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ this.filterByType(filteredRelays, filteredBridges, relaysRequested);
+ }
+ if (parameterMap.containsKey("running")) {
+ String runningParameterValue = parameterMap.get("running");
+ boolean runningRequested = true;
+ if (runningParameterValue.equals("false")) {
+ runningRequested = false;
+ } else if (!runningParameterValue.equals("true")) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ this.filterByRunning(filteredRelays, filteredBridges,
+ runningRequested);
+ }
+ if (parameterMap.containsKey("search")) {
+ String searchTerm = this.parseSearchParameter(
+ parameterMap.get("search"));
+ if (searchTerm == null) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ this.filterBySearchTerm(filteredRelays, filteredBridges,
+ searchTerm);
+ }
+ if (parameterMap.containsKey("lookup")) {
+ String fingerprintParameter = this.parseFingerprintParameter(
+ parameterMap.get("lookup"));
+ if (fingerprintParameter == null) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ String fingerprint = fingerprintParameter.toUpperCase();
+ this.filterByFingerprint(filteredRelays, filteredBridges,
+ fingerprint);
+ }
+
+ /* Re-order and limit results. */
+ List<String> orderedRelays = new ArrayList<String>();
+ List<String> orderedBridges = new ArrayList<String>();
+ if (parameterMap.containsKey("order")) {
+ String orderParameter = parameterMap.get("order");
+ boolean descending = false;
+ if (orderParameter.startsWith("-")) {
+ descending = true;
+ orderParameter = orderParameter.substring(1);
+ }
+ if (!orderParameter.equals("consensus_weight")) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
+ List<String> orderBy = new ArrayList<String>(
+ this.relaysByConsensusWeight);
+ if (descending) {
+ Collections.reverse(orderBy);
+ }
+ for (String relay : orderBy) {
+ if (filteredRelays.containsKey(relay) &&
+ !orderedRelays.contains(filteredRelays.get(relay))) {
+ orderedRelays.add(filteredRelays.remove(relay));
+ }
+ }
+ for (String relay : filteredRelays.values()) {
+ if (!orderedRelays.contains(filteredRelays.get(relay))) {
+ orderedRelays.add(filteredRelays.remove(relay));
+ }
+ }
+ Set<String> uniqueBridges = new HashSet<String>(
+ filteredBridges.values());
+ orderedBridges.addAll(uniqueBridges);
} else {
- response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return;
+ Set<String> uniqueRelays = new HashSet<String>(
+ filteredRelays.values());
+ orderedRelays.addAll(uniqueRelays);
+ Set<String> uniqueBridges = new HashSet<String>(
+ filteredBridges.values());
+ orderedBridges.addAll(uniqueBridges);
+ }
+ if (parameterMap.containsKey("offset")) {
+ String offsetParameter = parameterMap.get("offset");
+ if (offsetParameter.length() > 6) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ int offset = 0;
+ try {
+ offset = Integer.parseInt(offsetParameter);
+ } catch (NumberFormatException e) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ while (offset-- > 0 &&
+ (!orderedRelays.isEmpty() || !orderedBridges.isEmpty())) {
+ if (!orderedRelays.isEmpty()) {
+ orderedRelays.remove(0);
+ } else {
+ orderedBridges.remove(0);
+ }
+ }
+ }
+ if (parameterMap.containsKey("limit")) {
+ String limitParameter = parameterMap.get("limit");
+ if (limitParameter.length() > 6) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ int limit = -1;
+ try {
+ limit = Integer.parseInt(limitParameter);
+ } catch (NumberFormatException e) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ if (limit >= 0) {
+ while (limit < orderedRelays.size()) {
+ orderedRelays.remove(orderedRelays.size() - 1);
+ }
+ }
+ limit -= orderedRelays.size();
+ if (limit >= 0) {
+ while (limit < orderedBridges.size()) {
+ orderedBridges.remove(orderedBridges.size() - 1);
+ }
+ }
}
- /* Set response headers and start writing the response. */
+ /* Set response headers and write the response. */
response.setHeader("Access-Control-Allow-Origin", "*");
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
PrintWriter pw = response.getWriter();
+ this.writeRelays(orderedRelays, pw, resourceType);
+ this.writeBridges(orderedBridges, pw, resourceType);
+ pw.flush();
+ pw.close();
+ }
+
+ private Map<String, String> getParameterMapForOldStyleUri(String uri,
+ String resourceType) {
+ Map<String, String> result = new HashMap<String, String>();
if (uri.equals("/" + resourceType + "/all")) {
- pw.print(this.relaysPublishedLine + "\n");
- this.writeAllRelays(pw, resourceType);
- pw.print(this.bridgesPublishedLine + "\n");
- this.writeAllBridges(pw, resourceType);
} else if (uri.equals("/" + resourceType + "/running")) {
- pw.print(this.relaysPublishedLine + "\n");
- this.writeRunningRelays(pw, resourceType);
- pw.print(this.bridgesPublishedLine + "\n");
- this.writeRunningBridges(pw, resourceType);
+ result.put("running", "true");
} else if (uri.equals("/" + resourceType + "/relays")) {
- pw.print(this.relaysPublishedLine + "\n");
- this.writeAllRelays(pw, resourceType);
- pw.print(this.bridgesPublishedLine + "\n");
- this.writeNoBridges(pw);
+ result.put("type", "relays");
} else if (uri.equals("/" + resourceType + "/bridges")) {
- pw.print(this.relaysPublishedLine + "\n");
- this.writeNoRelays(pw);
- pw.print(this.bridgesPublishedLine + "\n");
- this.writeAllBridges(pw, resourceType);
+ result.put("type", "bridges");
} else if (uri.startsWith("/" + resourceType + "/search/")) {
String searchParameter = this.parseSearchParameter(uri.substring(
("/" + resourceType + "/search/").length()));
- pw.print(this.relaysPublishedLine + "\n");
- this.writeMatchingRelays(pw, searchParameter, resourceType);
- pw.print(this.bridgesPublishedLine + "\n");
- this.writeMatchingBridges(pw, searchParameter, resourceType);
+ if (searchParameter == null) {
+ result = null;
+ } else {
+ result.put("search", searchParameter);
+ }
} else if (uri.startsWith("/" + resourceType + "/lookup/")) {
- Set<String> fingerprintParameters = this.parseFingerprintParameters(
+ String fingerprintParameter = this.parseFingerprintParameter(
uri.substring(("/" + resourceType + "/lookup/").length()));
- pw.print(this.relaysPublishedLine + "\n");
- this.writeRelaysWithFingerprints(pw, fingerprintParameters,
- resourceType);
- pw.print(this.bridgesPublishedLine + "\n");
- this.writeBridgesWithFingerprints(pw, fingerprintParameters,
- resourceType);
+ if (fingerprintParameter == null) {
+ result = null;
+ } else {
+ result.put("lookup", fingerprintParameter);
+ }
+ } else {
+ result = null;
}
- pw.flush();
- pw.close();
+ return result;
}
private static Pattern searchParameterPattern =
@@ -223,180 +416,143 @@ public class ResourceServlet extends HttpServlet {
private static Pattern fingerprintParameterPattern =
Pattern.compile("^[0-9a-zA-Z]{1,40}$");
- private Set<String> parseFingerprintParameters(String parameter) {
+ private String parseFingerprintParameter(String parameter) {
if (!fingerprintParameterPattern.matcher(parameter).matches()) {
return null;
}
- Set<String> parsedFingerprints = new HashSet<String>();
if (parameter.length() != 40) {
return null;
}
- parsedFingerprints.add(parameter);
- return parsedFingerprints;
+ return parameter;
}
- private void writeAllRelays(PrintWriter pw, String resourceType) {
- pw.print("\"relays\":[");
- int written = 0;
- for (String line : this.relayLines) {
- String lines = this.getFromSummaryLine(line, resourceType);
- if (lines.length() > 0) {
- pw.print((written++ > 0 ? ",\n" : "\n") + lines);
- }
+ private void filterByType(Map<String, String> filteredRelays,
+ Map<String, String> filteredBridges, boolean relaysRequested) {
+ if (relaysRequested) {
+ filteredBridges.clear();
+ } else {
+ filteredRelays.clear();
}
- pw.print("],\n");
}
- private void writeRunningRelays(PrintWriter pw, String resourceType) {
- pw.print("\"relays\":[");
- int written = 0;
- for (String line : this.relayLines) {
- if (line.contains("\"r\":true")) {
- String lines = this.getFromSummaryLine(line, resourceType);
- if (lines.length() > 0) {
- pw.print((written++ > 0 ? ",\n" : "\n") + lines);
- }
+ private void filterByRunning(Map<String, String> filteredRelays,
+ Map<String, String> filteredBridges, boolean runningRequested) {
+ Set<String> removeRelays = new HashSet<String>();
+ for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
+ if (e.getValue().contains("\"r\":true") != runningRequested) {
+ removeRelays.add(e.getKey());
}
}
- pw.print("\n],\n");
- }
-
- private void writeNoRelays(PrintWriter pw) {
- pw.print("\"relays\":[\n");
- pw.print("],\n");
+ for (String fingerprint : removeRelays) {
+ filteredRelays.remove(fingerprint);
+ }
+ Set<String> removeBridges = new HashSet<String>();
+ for (Map.Entry<String, String> e : filteredBridges.entrySet()) {
+ if (e.getValue().contains("\"r\":true") != runningRequested) {
+ removeBridges.add(e.getKey());
+ }
+ }
+ for (String fingerprint : removeBridges) {
+ filteredBridges.remove(fingerprint);
+ }
}
- private void writeMatchingRelays(PrintWriter pw, String searchTerm,
- String resourceType) {
- if (searchTerm.length() == 40) {
- Set<String> fingerprints = new HashSet<String>();
- fingerprints.add(searchTerm);
- this.writeRelaysWithFingerprints(pw, fingerprints, resourceType);
- } else {
- pw.print("\"relays\":[");
- int written = 0;
- for (String line : this.relayLines) {
- boolean lineMatches = false;
- if (searchTerm.startsWith("$")) {
- /* Search is for $-prefixed fingerprint. */
- if (line.contains("\"f\":\""
- + searchTerm.substring(1).toUpperCase())) {
- /* $-prefixed fingerprint matches. */
- lineMatches = true;
- }
- } else if (line.toLowerCase().contains("\"n\":\""
- + searchTerm.toLowerCase())) {
- /* Nickname matches. */
+ private void filterBySearchTerm(Map<String, String> filteredRelays,
+ Map<String, String> filteredBridges, String searchTerm) {
+ Set<String> removeRelays = new HashSet<String>();
+ for (Map.Entry<String, String> e : filteredRelays.entrySet()) {
+ String line = e.getValue();
+ boolean lineMatches = false;
+ if (searchTerm.startsWith("$")) {
+ /* Search is for $-prefixed fingerprint. */
+ if (line.contains("\"f\":\""
+ + searchTerm.substring(1).toUpperCase())) {
+ /* $-prefixed fingerprint matches. */
lineMatches = true;
- } else if ("unnamed".startsWith(searchTerm.toLowerCase()) &&
- line.startsWith("{\"f\":")) {
- /* Nickname "Unnamed" matches. */
- lineMatches = true;
- } else if (line.contains("\"f\":\"" + searchTerm.toUpperCase())) {
- /* Non-$-prefixed fingerprint matches. */
- lineMatches = true;
- } else if (line.substring(line.indexOf("\"a\":[")).contains("\""
- + searchTerm.toLowerCase())) {
- /* Address matches. */
- lineMatches = true;
- }
- if (lineMatches) {
- String lines = this.getFromSummaryLine(line, resourceType);
- if (lines.length() > 0) {
- pw.print((written++ > 0 ? ",\n" : "\n") + lines);
- }
}
+ } else if (line.toLowerCase().contains("\"n\":\""
+ + searchTerm.toLowerCase())) {
+ /* Nickname matches. */
+ lineMatches = true;
+ } else if ("unnamed".startsWith(searchTerm.toLowerCase()) &&
+ line.startsWith("{\"f\":")) {
+ /* Nickname "Unnamed" matches. */
+ lineMatches = true;
+ } else if (line.contains("\"f\":\"" + searchTerm.toUpperCase())) {
+ /* Non-$-prefixed fingerprint matches. */
+ lineMatches = true;
+ } else if (line.substring(line.indexOf("\"a\":[")).contains("\""
+ + searchTerm.toLowerCase())) {
+ /* Address matches. */
+ lineMatches = true;
+ }
+ if (!lineMatches) {
+ removeRelays.add(e.getKey());
+ }
+ }
+ for (String fingerprint : removeRelays) {
+ filteredRelays.remove(fingerprint);
+ }
+ Set<String> removeBridges = new HashSet<String>();
+ if (searchTerm.startsWith("$")) {
+ searchTerm = searchTerm.substring(1);
+ }
+ for (Map.Entry<String, String> e : filteredBridges.entrySet()) {
+ String line = e.getValue();
+ if (!line.contains("\"h\":\"" + searchTerm.toUpperCase())) {
+ removeBridges.add(e.getKey());
}
- pw.print("\n],\n");
+ }
+ for (String fingerprint : removeBridges) {
+ filteredBridges.remove(fingerprint);
}
}
- private void writeRelaysWithFingerprints(PrintWriter pw,
- Set<String> fingerprints, String resourceType) {
- pw.print("\"relays\":[");
- int written = 0;
- for (String fingerprint : fingerprints) {
- if (this.relayFingerprintSummaryLines.containsKey(
- fingerprint.toUpperCase())) {
- String summaryLine = this.relayFingerprintSummaryLines.get(
- fingerprint.toUpperCase());
- String lines = this.getFromSummaryLine(summaryLine, resourceType);
- if (lines.length() > 0) {
- pw.print((written++ > 0 ? ",\n" : "\n") + lines);
- }
- }
+ private void filterByFingerprint(Map<String, String> filteredRelays,
+ Map<String, String> filteredBridges, String fingerprint) {
+ String relayLine = filteredRelays.get(fingerprint);
+ filteredRelays.clear();
+ if (relayLine != null) {
+ filteredRelays.put(fingerprint, relayLine);
+ }
+ String bridgeLine = filteredBridges.get(fingerprint);
+ filteredBridges.clear();
+ if (bridgeLine != null) {
+ filteredBridges.put(fingerprint, bridgeLine);
}
- pw.print("\n],\n");
}
- private void writeAllBridges(PrintWriter pw, String resourceType) {
- pw.print("\"bridges\":[");
+ private void writeRelays(List<String> relays, PrintWriter pw,
+ String resourceType) {
+ pw.print(this.relaysPublishedLine + "\n");
+ pw.print("\"relays\":[");
int written = 0;
- for (String line : this.bridgeLines) {
+ for (String line : relays) {
+ if (line == null) {
+ /* TODO This is a workaround for a bug; line shouldn't be null. */
+ continue;
+ }
String lines = this.getFromSummaryLine(line, resourceType);
if (lines.length() > 0) {
pw.print((written++ > 0 ? ",\n" : "\n") + lines);
}
}
- pw.print("\n]}\n");
- }
-
- private void writeRunningBridges(PrintWriter pw, String resourceType) {
- pw.print("\"bridges\":[");
- int written = 0;
- for (String line : this.bridgeLines) {
- if (line.contains("\"r\":true")) {
- String lines = this.getFromSummaryLine(line, resourceType);
- if (lines.length() > 0) {
- pw.print((written++ > 0 ? ",\n" : "\n") + lines);
- }
- }
- }
- pw.print("\n]}\n");
- }
-
- private void writeNoBridges(PrintWriter pw) {
- pw.print("\"bridges\":[\n");
- pw.print("]}\n");
+ pw.print("\n],\n");
}
- private void writeMatchingBridges(PrintWriter pw, String searchTerm,
+ private void writeBridges(List<String> bridges, PrintWriter pw,
String resourceType) {
- if (searchTerm.startsWith("$")) {
- searchTerm = searchTerm.substring(1);
- }
- if (searchTerm.length() == 40) {
- Set<String> fingerprints = new HashSet<String>();
- fingerprints.add(searchTerm);
- this.writeBridgesWithFingerprints(pw, fingerprints, resourceType);
- } else {
- pw.print("\"bridges\":[");
- int written = 0;
- for (String line : this.bridgeLines) {
- if (line.contains("\"h\":\"" + searchTerm.toUpperCase())) {
- String lines = this.getFromSummaryLine(line, resourceType);
- if (lines.length() > 0) {
- pw.print((written++ > 0 ? ",\n" : "\n") + lines);
- }
- }
- }
- pw.print("\n]}\n");
- }
- }
-
- private void writeBridgesWithFingerprints(PrintWriter pw,
- Set<String> fingerprints, String resourceType) {
+ pw.print(this.bridgesPublishedLine + "\n");
pw.print("\"bridges\":[");
int written = 0;
- for (String fingerprint : fingerprints) {
- if (this.bridgeFingerprintSummaryLines.containsKey(
- fingerprint.toUpperCase())) {
- String summaryLine = this.bridgeFingerprintSummaryLines.get(
- fingerprint.toUpperCase());
- String lines = this.getFromSummaryLine(summaryLine, resourceType);
- if (lines.length() > 0) {
- pw.print((written++ > 0 ? ",\n" : "\n") + lines);
- }
+ for (String line : bridges) {
+ if (line == null) {
+ /* TODO This is a workaround for a bug; line shouldn't be null. */
+ continue;
+ }
+ String lines = this.getFromSummaryLine(line, resourceType);
+ if (lines.length() > 0) {
+ pw.print((written++ > 0 ? ",\n" : "\n") + lines);
}
}
pw.print("\n]}\n");
diff --git a/web/index.html b/web/index.html
index c4c154c..7a73591 100755
--- a/web/index.html
+++ b/web/index.html
@@ -84,7 +84,11 @@ Required field.</li>
<p>The following methods are available that all return a single summary
document.
The method and its parameters determines which relay and/or bridge
-summaries are included in the response.</p>
+summaries are included in the response.
+<font color="red">These methods have been deprecated on April 3, 2012 and
+will be removed after June 3, 2012.
+See the Methods section at the end of this page.</font>
+</p>
<table border="0" cellpadding="4" cellspacing="0" summary="">
<colgroup>
<col width="350">
@@ -93,22 +97,34 @@ summaries are included in the response.</p>
<tr>
<td><b>GET summary/all</b></td>
<td>Return summaries of all relays and bridges that are currently running
-or that have been running in the past week.</td>
+or that have been running in the past week.
+<font color="red">New method:
+<b>GET summary</b></font>
+</td>
</tr>
<tr>
<td><b>GET summary/running</b></td>
<td>Return summaries of all relays and bridges that are currently
-running.</td>
+running.
+<font color="red">New method:
+<b>GET summary?running=true</b></font>
+</td>
</tr>
<tr>
<td><b>GET summary/relays</b></td>
<td>Return summaries of all relays that are currently running or that have
-been running in the past week, but don't include any bridges.</td>
+been running in the past week, but don't include any bridges.
+<font color="red">New method:
+<b>GET summary?type=relay</b></font>
+</td>
</tr>
<tr>
<td><b>GET summary/bridges</b></td>
<td>Return summaries of all bridges that are currently running or that
-have been running in the past week, but don't include any relays.</td>
+have been running in the past week, but don't include any relays.
+<font color="red">New method:
+<b>GET summary?type=bridge</b></font>
+</td>
</tr>
<tr>
<td><b>GET summary/search/<i>:searchtext</i></b></td>
@@ -119,7 +135,10 @@ Searches are case-insensitive.
<font color="blue">Full fingerprints should always be hashed using SHA-1,
regardless of searching for a relay or a bridge, in order to not
accidentally leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to search for hashed fingerprints on March 19, 2012.</td>
+Added the option to search for hashed fingerprints on March 19, 2012.
+<font color="red">New method:
+<b>GET summary?search=:searchtext</b></font>
+</td>
</tr>
<tr>
<td><b>GET summary/lookup/<i>:fingerprint</i></b></td>
@@ -128,7 +147,10 @@ matching the fingerprint or hashed fingerprint.
<font color="blue">Fingerprints should always be hashed using SHA-1,
regardless of looking up a relay or a bridge, in order to not accidentally
leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to look up hashed fingerprints on March 19, 2012.</td>
+Added the option to look up hashed fingerprints on March 19, 2012.
+<font color="red">New method:
+<b>GET summary?lookup=:fingerprint</b></font>
+</td>
</tr>
</table>
<br>
@@ -304,7 +326,11 @@ Optional field.</li>
<p>The following methods are available that all return a single details
document.
The method and its parameters determines which relay and/or bridge
-details are included in the response.</p>
+details are included in the response.
+<font color="red">These methods have been deprecated on April 3, 2012 and
+will be removed after June 3, 2012.
+See the Methods section at the end of this page.</font>
+</p>
<table border="0" cellpadding="4" cellspacing="0" summary="">
<colgroup>
<col width="350">
@@ -313,22 +339,34 @@ details are included in the response.</p>
<tr>
<td><b>GET details/all</b></td>
<td>Return details of all relays and bridges that are currently running
-or that have been running in the past week.</td>
+or that have been running in the past week.
+<font color="red">New method:
+<b>GET details</b></font>
+</td>
</tr>
<tr>
<td><b>GET details/running</b></td>
<td>Return details of all relays and bridges that are currently
-running.</td>
+running.
+<font color="red">New method:
+<b>GET details?running=true</b></font>
+</td>
</tr>
<tr>
<td><b>GET details/relays</b></td>
<td>Return details of all relays that are currently running or that have
-been running in the past week, but don't include any bridges.</td>
+been running in the past week, but don't include any bridges.
+<font color="red">New method:
+<b>GET details?type=relay</b></font>
+</td>
</tr>
<tr>
<td><b>GET details/bridges</b></td>
<td>Return details of all bridges that are currently running or that have
-been running in the past week, but don't include any relays.</td>
+been running in the past week, but don't include any relays.
+<font color="red">New method:
+<b>GET details?type=bridge</b></font>
+</td>
</tr>
<tr>
<td><b>GET details/search/<i>:searchtext</i></b></td>
@@ -339,7 +377,10 @@ Searches are case-insensitive.
<font color="blue">Full fingerprints should always be hashed using SHA-1,
regardless of searching for a relay or a bridge, in order to not
accidentally leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to search for hashed fingerprints on March 19, 2012.</td>
+Added the option to search for hashed fingerprints on March 19, 2012.
+<font color="red">New method:
+<b>GET details?search=:searchtext</b></font>
+</td>
</tr>
<tr>
<td><b>GET details/lookup/<i>:fingerprint</i></b></td>
@@ -348,7 +389,10 @@ matching the fingerprint or hashed fingerprint.
<font color="blue">Fingerprints should always be hashed using SHA-1,
regardless of looking up a relay or a bridge, in order to not accidentally
leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to look up hashed fingerprints on March 19, 2012.</td>
+Added the option to look up hashed fingerprints on March 19, 2012.
+<font color="red">New method:
+<b>GET details?lookup=:fingerprint</b></font>
+</td>
</tr>
</table>
<br>
@@ -446,7 +490,11 @@ The specification of bandwidth history objects is similar to those in the
</ul>
<p>The following methods are available that all return a single document.
The method and its parameters determines which relay and/or bridge
-bandwidth documents are included in the response.</p>
+bandwidth documents are included in the response.
+<font color="red">These methods have been deprecated on April 3, 2012 and
+will be removed after June 3, 2012.
+See the Methods section at the end of this page.</font>
+</p>
<table border="0" cellpadding="4" cellspacing="0" summary="">
<colgroup>
<col width="350">
@@ -455,23 +503,35 @@ bandwidth documents are included in the response.</p>
<tr>
<td><b>GET bandwidth/all</b></td>
<td>Return bandwidth documents of all relays and bridges that are
-currently running or that have been running in the past week.</td>
+currently running or that have been running in the past week.
+<font color="red">New method:
+<b>GET bandwidth</b></font>
+</td>
</tr>
<tr>
<td><b>GET bandwidth/running</b></td>
<td>Return bandwidth documents of all relays and bridges that are
-currently running.</td>
+currently running.
+<font color="red">New method:
+<b>GET bandwidth?running=true</b></font>
+</td>
</tr>
<tr>
<td><b>GET bandwidth/relays</b></td>
<td>Return bandwidth documents of all relays that are currently running or
-that have been running in the past week, but don't include any bridges.</td>
+that have been running in the past week, but don't include any bridges.
+<font color="red">New method:
+<b>GET bandwidth?type=relay</b></font>
+</td>
</tr>
<tr>
<td><b>GET bandwidth/bridges</b></td>
<td>Return bandwidth documents of all bridges that are currently running
or that have been running in the past week, but don't include any
-relays.</td>
+relays.
+<font color="red">New method:
+<b>GET bandwidth?type=bridge</b></font>
+</td>
</tr>
<tr>
<td><b>GET details/search/<i>:searchtext</i></b></td>
@@ -483,7 +543,10 @@ Searches are case-insensitive.
<font color="blue">Full fingerprints should always be hashed using SHA-1,
regardless of searching for a relay or a bridge, in order to not
accidentally leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to search for hashed fingerprints on March 19, 2012.</td>
+Added the option to search for hashed fingerprints on March 19, 2012.
+<font color="red">New method:
+<b>GET bandwidth?search=:searchtext</b></font>
+</td>
</tr>
<tr>
<td><b>GET bandwidth/lookup/<i>:fingerprint</i></b></td>
@@ -492,9 +555,110 @@ Added the option to search for hashed fingerprints on March 19, 2012.</td>
<font color="blue">Fingerprints should always be hashed using SHA-1,
regardless of looking up a relay or a bridge, in order to not accidentally
leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to look up hashed fingerprints on March 19, 2012.</td>
+Added the option to look up hashed fingerprints on March 19, 2012.
+<font color="red">New method:
+<b>GET bandwidth?lookup=:fingerprint</b></font>
+</td>
</tr>
</table>
+<br>
+<h3>Methods</h3>
+<p>The following methods each return a single document containing zero or
+more relay and/or bridge documents.</p>
+<table border="0" cellpadding="4" cellspacing="0" summary="">
+<colgroup>
+<col width="150">
+<col width="850">
+</colgroup>
+<tr>
+<td><b>GET summary</b></td>
+<td>Return summaries of all relays and bridges that are currently running
+or that have been running in the past week.
+<font color="blue">Method added on April 3, 2012.</font>
+</td>
+</tr>
+<tr>
+<td><b>GET details</b></td>
+<td>Return details of all relays and bridges that are currently running
+or that have been running in the past week.
+<font color="blue">Method added on April 3, 2012.</font>
+</td>
+</tr>
+<tr>
+<td><b>GET bandwidth</b></td>
+<td>Return bandwidth documents of all relays and bridges that are
+currently running or that have been running in the past week.
+<font color="blue">Method added on April 3, 2012.</font>
+</td>
+</tr>
+</table>
+<p>Each of the methods above can be parameterized to select only a subset
+of relay and/or bridge documents to be included in the response.</p>
+<table border="0" cellpadding="4" cellspacing="0" summary="">
+<colgroup>
+<col width="150">
+<col width="850">
+</colgroup>
+<tr><td><b>type</b></td><td>Return only relay (parameter value
+<b>relay</b>) or only bridge documents (parameter value
+<b>bridge</b>).
+<font color="blue">Parameter added on April 3, 2012.</font>
+</td></tr>
+<tr><td><b>running</b></td><td>Return only running (parameter value
+<b>true</b>) or only non-running relays and/or bridges (paramter value
+<b>false</b>).
+<font color="blue">Parameter added on April 3, 2012.</font>
+</td></tr>
+<tr><td><b>search</b></td><td>Return only relays with the parameter value
+matching the beginning of a nickname, (possibly $-prefixed) fingerprint,
+or IP address, and bridges with the (possibly $-prefixed) hashed
+fingerprint.
+Searches are case-insensitive.
+Full fingerprints should always be hashed using SHA-1, regardless of
+searching for a relay or a bridge, in order to not accidentally leak
+non-hashed bridge fingerprints in the URL.
+<font color="blue">Parameter added on April 3, 2012.</font>
+</td></tr>
+<tr><td><b>lookup</b></td><td>Return only the relay with the parameter
+value matching the fingerprint or the bridge with the parameter value
+matching the hashed fingerprint.
+Fingerprints should always be hashed using SHA-1, regardless of looking up
+a relay or a bridge, in order to not accidentally leak non-hashed bridge
+fingerprints in the URL.
+<font color="blue">Parameter added on April 3, 2012.</font>
+</td></tr>
+</table>
+<p>Relay and/or bridge documents in the response can be ordered and
+limited by providing further parameters.</p>
+<table border="0" cellpadding="4" cellspacing="0" summary="">
+<colgroup>
+<col width="150">
+<col width="850">
+</colgroup>
+<tr><td><b>order</b></td><td>Re-order results by a comma-separated list
+of fields in ascending or descening order.
+Results are first ordered by the second list element, then by the second,
+and so on.
+Possible fields for ordering are: <b>consensus_weight</b>.
+Ascending order is the default; descending order is selected by prepending
+fields with a minus sign (<b>-</b>).
+Relays which don't have any value for a field to be ordered by are always
+appended to the end, regardless or sorting order.
+If no <b>order</b> parameter is given, ordering of results is
+undefined.
+<font color="blue">Parameter added on April 3, 2012.</font>
+</td></tr>
+<tr><td><b>offset</b></td><td>Skip the given number of relays and/or
+bridges.
+<font color="blue">Parameter added on April 3, 2012.</font>
+</td></tr>
+<tr><td><b>limit</b></td><td>Limit result to the given number of
+relays and/or bridges.
+When used together with <b>offset</b>, the offsetting step precedes the
+limiting step.
+<font color="blue">Parameter added on April 3, 2012.</font>
+</td></tr>
+</table>
</body>
</html>
1
0

[onionoo/master] Remove announced changes that are more than 1 month old.
by karsten@torproject.org 14 May '12
by karsten@torproject.org 14 May '12
14 May '12
commit aebe36263741c6edc8b8eb2b8769cebcc1ead9ee
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon May 14 15:00:30 2012 +0200
Remove announced changes that are more than 1 month old.
---
web/index.html | 70 ++++++++++++++++++++++++-------------------------------
1 files changed, 31 insertions(+), 39 deletions(-)
diff --git a/web/index.html b/web/index.html
index 3b15077..93c798e 100755
--- a/web/index.html
+++ b/web/index.html
@@ -132,10 +132,9 @@ have been running in the past week, but don't include any relays.
matching the beginning of a nickname, (possibly $-prefixed) fingerprint,
IP address, or (possibly $-prefixed) hashed fingerprint.
Searches are case-insensitive.
-<font color="blue">Full fingerprints should always be hashed using SHA-1,
-regardless of searching for a relay or a bridge, in order to not
-accidentally leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to search for hashed fingerprints on March 19, 2012.
+Full fingerprints should always be hashed using SHA-1, regardless of
+searching for a relay or a bridge, in order to not accidentally leak
+non-hashed bridge fingerprints in the URL.
<font color="red">New method:
<b>GET summary?search=:searchtext</b></font>
</td>
@@ -144,10 +143,9 @@ Added the option to search for hashed fingerprints on March 19, 2012.
<td><b>GET summary/lookup/<i>:fingerprint</i></b></td>
<td>Return the summary of the relay or bridge with <i>:fingerprint</i>
matching the fingerprint or hashed fingerprint.
-<font color="blue">Fingerprints should always be hashed using SHA-1,
-regardless of looking up a relay or a bridge, in order to not accidentally
-leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to look up hashed fingerprints on March 19, 2012.
+Fingerprints should always be hashed using SHA-1, regardless of looking up
+a relay or a bridge, in order to not accidentally leak non-hashed bridge
+fingerprints in the URL.
<font color="red">New method:
<b>GET summary?lookup=:fingerprint</b></font>
</td>
@@ -245,18 +243,16 @@ Required field.
Added on May 14, 2012.</li>
<li><b>"last_restarted":</b> UTC timestamp (YYYY-MM-DD hh:mm:ss) when the
relay was last (re-)started.
-<font color="red">Optional field.</font>
-Missing if router descriptor containing this information cannot be found.
-Made field optional on March 5, 2012.</li>
+Optional field.</li>
<li><b>"advertised_bandwidth":</b> Bandwidth in bytes per second that this
relay is willing and capable to provide.
-<font color="red">Optional field.</font>
-Missing if router descriptor containing this information cannot be found.
-Made field optional on March 5, 2012.</li>
+Optional field.
+Missing if router descriptor containing this information cannot be
+found.</li>
<li><b>"exit_policy":</b> Array of exit-policy lines.
-<font color="red">Optional field.</font>
-Missing if router descriptor containing this information cannot be found.
-Made field optional on March 5, 2012.</li>
+Optional field.
+Missing if router descriptor containing this information cannot be
+found.</li>
<li><b>"contact":</b> Contact address of the relay operator.
Omitted if empty or if descriptor containing this information cannot be
found.</li>
@@ -303,14 +299,14 @@ Optional field.
Omitted if empty.</li>
<li><b>"last_restarted":</b> UTC timestamp (YYYY-MM-DD hh:mm:ss) when the
bridge was last (re-)started.
-<font color="red">Optional field.</font>
-Missing if router descriptor containing this information cannot be found.
-Made field optional on March 5, 2012.</li>
+Optional field.
+Missing if router descriptor containing this information cannot be
+found.</li>
<li><b>"advertised_bandwidth":</b> Bandwidth in bytes per second that this
bridge is willing and capable to provide.
-<font color="red">Optional field.</font>
-Missing if router descriptor containing this information cannot be found.
-Made field optional on March 5, 2012.</li>
+Optional field.
+Missing if router descriptor containing this information cannot be
+found.</li>
<li><b>"platform":</b> Platform string containing operating system and Tor
version details.
Optional field.
@@ -374,10 +370,9 @@ been running in the past week, but don't include any relays.
matching the beginning of a nickname, (possibly $-prefixed) fingerprint,
IP address, or (possibly $-prefixed) hashed fingerprint.
Searches are case-insensitive.
-<font color="blue">Full fingerprints should always be hashed using SHA-1,
-regardless of searching for a relay or a bridge, in order to not
-accidentally leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to search for hashed fingerprints on March 19, 2012.
+Full fingerprints should always be hashed using SHA-1, regardless of
+searching for a relay or a bridge, in order to not accidentally leak
+non-hashed bridge fingerprints in the URL.
<font color="red">New method:
<b>GET details?search=:searchtext</b></font>
</td>
@@ -386,10 +381,9 @@ Added the option to search for hashed fingerprints on March 19, 2012.
<td><b>GET details/lookup/<i>:fingerprint</i></b></td>
<td>Return the details of the relay or bridge with <i>:fingerprint</i>
matching the fingerprint or hashed fingerprint.
-<font color="blue">Fingerprints should always be hashed using SHA-1,
-regardless of looking up a relay or a bridge, in order to not accidentally
-leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to look up hashed fingerprints on March 19, 2012.
+Fingerprints should always be hashed using SHA-1, regardless of looking up
+a relay or a bridge, in order to not accidentally leak non-hashed bridge
+fingerprints in the URL.
<font color="red">New method:
<b>GET details?lookup=:fingerprint</b></font>
</td>
@@ -540,10 +534,9 @@ relays.
$-prefixed) fingerprint, IP address, or (possibly $-prefixed) hashed
fingerprint.
Searches are case-insensitive.
-<font color="blue">Full fingerprints should always be hashed using SHA-1,
-regardless of searching for a relay or a bridge, in order to not
-accidentally leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to search for hashed fingerprints on March 19, 2012.
+Full fingerprints should always be hashed using SHA-1, regardless of
+searching for a relay or a bridge, in order to not accidentally leak
+non-hashed bridge fingerprints in the URL.
<font color="red">New method:
<b>GET bandwidth?search=:searchtext</b></font>
</td>
@@ -552,10 +545,9 @@ Added the option to search for hashed fingerprints on March 19, 2012.
<td><b>GET bandwidth/lookup/<i>:fingerprint</i></b></td>
<td>Return the bandwidth document of the relay or bridge with
<i>:fingerprint</i> matching the fingerprint or hashed fingerprint.
-<font color="blue">Fingerprints should always be hashed using SHA-1,
-regardless of looking up a relay or a bridge, in order to not accidentally
-leak non-hashed bridge fingerprints in the URL.</font>
-Added the option to look up hashed fingerprints on March 19, 2012.
+Fingerprints should always be hashed using SHA-1, regardless of looking up
+a relay or a bridge, in order to not accidentally leak non-hashed bridge
+fingerprints in the URL.
<font color="red">New method:
<b>GET bandwidth?lookup=:fingerprint</b></font>
</td>
1
0

[translation/vidalia_completed] Update translations for vidalia_completed
by translation@torproject.org 14 May '12
by translation@torproject.org 14 May '12
14 May '12
commit e754d9872a442b48e2270793a0e0ef9f0cb67ea7
Author: Translation commit bot <translation(a)torproject.org>
Date: Mon May 14 12:45:10 2012 +0000
Update translations for vidalia_completed
---
hr_HR/qt_hr_HR.po | 435 ++++++
hr_HR/vidalia_hr_HR.po | 3847 ++++++++++++++++++++++++++++++++++++++++++++++++
ko_KR/qt_ko_KR.po | 434 ++++++
3 files changed, 4716 insertions(+), 0 deletions(-)
diff --git a/hr_HR/qt_hr_HR.po b/hr_HR/qt_hr_HR.po
new file mode 100644
index 0000000..f309161
--- /dev/null
+++ b/hr_HR/qt_hr_HR.po
@@ -0,0 +1,435 @@
+# Translators:
+# Translators:
+# Armando Vega <synaan(a)gmail.com>, 2012.
+# <trebelnik2(a)gmail.com>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: The Tor Project\n"
+"Report-Msgid-Bugs-To: https://trac.torproject.org/projects/tor\n"
+"POT-Creation-Date: 2008-08-20 03:25+0000\n"
+"PO-Revision-Date: 2012-05-09 08:52+0000\n"
+"Last-Translator: gogo <trebelnik2(a)gmail.com>\n"
+"Language-Team: none\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: hr_HR\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+"X-Generator: Vidalia ts2po 0.2\n"
+
+#: qaccessibleobject.cpp:348
+msgctxt "QApplication"
+msgid "Activate"
+msgstr "Aktiviraj"
+
+#: qmessagebox.h:319
+msgctxt "QApplication"
+msgid "Executable '%1' requires Qt %2, found Qt %3."
+msgstr "Izvršna datoteka '%1' zahtjeva Qt %2, pronađen Qt %3."
+
+#: qmessagebox.h:321
+msgctxt "QApplication"
+msgid "Incompatible Qt Library Error"
+msgstr "Greška nekompatibilne Qt knjižnice"
+
+#: qapplication.cpp:2095
+msgctxt "QApplication"
+msgid "QT_LAYOUT_DIRECTION"
+msgstr "QT_SMJER_RASPOREDA"
+
+#: qaccessibleobject.cpp:350
+msgctxt "QApplication"
+msgid "Activates the program's main window"
+msgstr "Aktivira glavni prozor aplikacije"
+
+#: qmessagebox.cpp:2104
+msgctxt "QDialogButtonBox"
+msgid "OK"
+msgstr "OK"
+
+#: qdialogbuttonbox.cpp:528
+msgctxt "QDialogButtonBox"
+msgid "Save"
+msgstr "Spremi"
+
+#: qdialogbuttonbox.cpp:531
+msgctxt "QDialogButtonBox"
+msgid "Open"
+msgstr "Otvori"
+
+#: qdialogbuttonbox.cpp:534
+msgctxt "QDialogButtonBox"
+msgid "Cancel"
+msgstr "Odustani"
+
+#: qdialogbuttonbox.cpp:537
+msgctxt "QDialogButtonBox"
+msgid "Close"
+msgstr "Zatvori"
+
+#: qdialogbuttonbox.cpp:540
+msgctxt "QDialogButtonBox"
+msgid "Apply"
+msgstr "Primjeni"
+
+#: qdialogbuttonbox.cpp:543
+msgctxt "QDialogButtonBox"
+msgid "Reset"
+msgstr "Poništi"
+
+#: qdialogbuttonbox.cpp:546
+msgctxt "QDialogButtonBox"
+msgid "Help"
+msgstr "Pomoć"
+
+#: qdialogbuttonbox.cpp:550
+msgctxt "QDialogButtonBox"
+msgid "Don't Save"
+msgstr "Ne spremaj"
+
+#: qdialogbuttonbox.cpp:554
+msgctxt "QDialogButtonBox"
+msgid "Discard"
+msgstr "Odbaci"
+
+#: qdialogbuttonbox.cpp:557
+msgctxt "QDialogButtonBox"
+msgid "&Yes"
+msgstr "&Da"
+
+#: qdialogbuttonbox.cpp:560
+msgctxt "QDialogButtonBox"
+msgid "Yes to &All"
+msgstr "Da z&a sve"
+
+#: qdialogbuttonbox.cpp:563
+msgctxt "QDialogButtonBox"
+msgid "&No"
+msgstr "&Ne"
+
+#: qdialogbuttonbox.cpp:566
+msgctxt "QDialogButtonBox"
+msgid "N&o to All"
+msgstr "N&e za sve"
+
+#: qdialogbuttonbox.cpp:569
+msgctxt "QDialogButtonBox"
+msgid "Save All"
+msgstr "Spremi sve"
+
+#: qdialogbuttonbox.cpp:572
+msgctxt "QDialogButtonBox"
+msgid "Abort"
+msgstr "Prekini"
+
+#: qdialogbuttonbox.cpp:575
+msgctxt "QDialogButtonBox"
+msgid "Retry"
+msgstr "Pokušaj ponovno"
+
+#: qdialogbuttonbox.cpp:578
+msgctxt "QDialogButtonBox"
+msgid "Ignore"
+msgstr "Ignoriraj"
+
+#: qdialogbuttonbox.cpp:581
+msgctxt "QDialogButtonBox"
+msgid "Restore Defaults"
+msgstr "Vrati uobičajeno"
+
+#: qdialogbuttonbox.cpp:552
+msgctxt "QDialogButtonBox"
+msgid "Close without Saving"
+msgstr "Zatvori bez spremanja"
+
+#: qdialogbuttonbox.cpp:525
+msgctxt "QDialogButtonBox"
+msgid "&OK"
+msgstr "&U redu"
+
+#: qdirmodel.cpp:423
+msgctxt "QDirModel"
+msgid "Name"
+msgstr "Naziv"
+
+#: qdirmodel.cpp:424
+msgctxt "QDirModel"
+msgid "Size"
+msgstr "Veličina"
+
+#: qdirmodel.cpp:427
+msgctxt "QDirModel"
+msgid "Kind"
+msgstr "Vrsta"
+
+#: qdirmodel.cpp:429
+msgctxt "QDirModel"
+msgid "Type"
+msgstr "Tip"
+
+#: qdirmodel.cpp:435
+msgctxt "QDirModel"
+msgid "Date Modified"
+msgstr "Datum izmjene"
+
+#: qfiledialog_win.cpp:126
+msgctxt "QFileDialog"
+msgid "All Files (*)"
+msgstr "Sve datoteke(*)"
+
+#: qfiledialog.cpp:881
+msgctxt "QFileDialog"
+msgid "Directories"
+msgstr "Direktoriji"
+
+#: qfiledialog.cpp:2408
+msgctxt "QFileDialog"
+msgid "&Open"
+msgstr "&Otvori"
+
+#: qfiledialog.cpp:919
+msgctxt "QFileDialog"
+msgid "&Save"
+msgstr "&Spremi"
+
+#: qfiledialog.cpp:435
+msgctxt "QFileDialog"
+msgid "Open"
+msgstr "Otvori"
+
+#: qfiledialog.cpp:1670
+msgctxt "QFileDialog"
+msgid ""
+"%1 already exists.\n"
+"Do you want to replace it?"
+msgstr "%1 već postoji.\nŽelite li ju zamjeniti?"
+
+#: qfiledialog.cpp:1690
+msgctxt "QFileDialog"
+msgid ""
+"%1\n"
+"File not found.\n"
+"Please verify the correct file name was given."
+msgstr "%1\nDatoteka nije pronađena.\nMolimo provjerite točnost datog naziva datoteke."
+
+#: qdirmodel.cpp:833
+msgctxt "QFileDialog"
+msgid "My Computer"
+msgstr "Moje Računalo"
+
+#: qfiledialog.cpp:462
+msgctxt "QFileDialog"
+msgid "&Rename"
+msgstr "P&reimenuj"
+
+#: qfiledialog.cpp:463
+msgctxt "QFileDialog"
+msgid "&Delete"
+msgstr "&Izbriši"
+
+#: qfiledialog.cpp:464
+msgctxt "QFileDialog"
+msgid "Show &hidden files"
+msgstr "Prikaži skrivene datoteke"
+
+#: ui_qfiledialog.h:264
+msgctxt "QFileDialog"
+msgid "Back"
+msgstr "Natrag"
+
+#: ui_qfiledialog.h:274
+msgctxt "QFileDialog"
+msgid "Parent Directory"
+msgstr "Nadređeni direktorij"
+
+#: ui_qfiledialog.h:284
+msgctxt "QFileDialog"
+msgid "List View"
+msgstr "Popisni pogled"
+
+#: ui_qfiledialog.h:289
+msgctxt "QFileDialog"
+msgid "Detail View"
+msgstr "Detaljni pogled"
+
+#: ui_qfiledialog.h:292
+msgctxt "QFileDialog"
+msgid "Files of type:"
+msgstr "Vrsta datoteka:"
+
+#: qfiledialog.cpp:883
+msgctxt "QFileDialog"
+msgid "Directory:"
+msgstr "Direktorij:"
+
+#: qfiledialog.cpp:2476
+msgctxt "QFileDialog"
+msgid ""
+"%1\n"
+"Directory not found.\n"
+"Please verify the correct directory name was given."
+msgstr "%1\nDirektorij nije pronađen.\nMolimo provjerite točnost naziva datog direktorija."
+
+#: qfiledialog.cpp:2281
+msgctxt "QFileDialog"
+msgid ""
+"'%1' is write protected.\n"
+"Do you want to delete it anyway?"
+msgstr "'%1' je zaštićena od pisanja.\nŽelite li ju svejedno izbrisati?"
+
+#: qfiledialog.cpp:2286
+msgctxt "QFileDialog"
+msgid "Are sure you want to delete '%1'?"
+msgstr "Sigurno želite izbrisati '%1'?"
+
+#: qfiledialog.cpp:2299
+msgctxt "QFileDialog"
+msgid "Could not delete directory."
+msgstr "Nemoguće brisanje direktorija."
+
+#: qfiledialog_win.cpp:128
+msgctxt "QFileDialog"
+msgid "All Files (*.*)"
+msgstr "Sve datoteke (*.*)"
+
+#: qfiledialog.cpp:437
+msgctxt "QFileDialog"
+msgid "Save As"
+msgstr "Spremi kao"
+
+#: qfileiconprovider.cpp:379
+msgctxt "QFileDialog"
+msgid "Drive"
+msgstr "Pogon"
+
+#: qfileiconprovider.cpp:383
+msgctxt "QFileDialog"
+msgid "File"
+msgstr "Datoteka"
+
+#: qfileiconprovider.cpp:412
+msgctxt "QFileDialog"
+msgid "Unknown"
+msgstr "Nepoznato"
+
+#: qfiledialog.cpp:439
+msgctxt "QFileDialog"
+msgid "Find Directory"
+msgstr "Pronađi direktorij"
+
+#: qfiledialog.cpp:458
+msgctxt "QFileDialog"
+msgid "Show "
+msgstr "Prikaži "
+
+#: ui_qfiledialog.h:269
+msgctxt "QFileDialog"
+msgid "Forward"
+msgstr "Naprijed"
+
+#: qfiledialog.cpp:2137
+msgctxt "QFileDialog"
+msgid "New Folder"
+msgstr "Nova mapa"
+
+#: qfiledialog.cpp:465
+msgctxt "QFileDialog"
+msgid "&New Folder"
+msgstr "&Nova mapa"
+
+#: qfiledialog.cpp:917
+msgctxt "QFileDialog"
+msgid "&Choose"
+msgstr "&Odaberi"
+
+#: qsidebar.cpp:388
+msgctxt "QFileDialog"
+msgid "Remove"
+msgstr "Ukloni"
+
+#: qfiledialog.cpp:886
+msgctxt "QFileDialog"
+msgid "File &name:"
+msgstr "Naziv datoteke:"
+
+#: ui_qfiledialog.h:261
+msgctxt "QFileDialog"
+msgid "Look in:"
+msgstr "Pogledaj u:"
+
+#: ui_qfiledialog.h:279
+msgctxt "QFileDialog"
+msgid "Create New Folder"
+msgstr "Stvori novu mapu"
+
+#: qfilesystemmodel.cpp:761
+msgctxt "QFileSystemModel"
+msgid "Invalid filename"
+msgstr "Neispravni naziv datoteke"
+
+#: qfilesystemmodel.cpp:763
+msgctxt "QFileSystemModel"
+msgid ""
+"<b>The name \"%1\" can not be used.</b><p>Try using another name, with fewer"
+" characters or no punctuations marks."
+msgstr "<b>Naziv \"%1\" nije moguće koristiti.</b><p>Pokušajte koristiti drugi naziv, sa manje znakova ili bez interpunkcijskih znakova."
+
+#: qfilesystemmodel.cpp:832
+msgctxt "QFileSystemModel"
+msgid "Name"
+msgstr "Naziv"
+
+#: qfilesystemmodel.cpp:834
+msgctxt "QFileSystemModel"
+msgid "Size"
+msgstr "Veličina"
+
+#: qfilesystemmodel.cpp:838
+msgctxt "QFileSystemModel"
+msgid "Kind"
+msgstr "Vrsta"
+
+#: qfilesystemmodel.cpp:840
+msgctxt "QFileSystemModel"
+msgid "Type"
+msgstr "Tip"
+
+#: qfilesystemmodel.cpp:847
+msgctxt "QFileSystemModel"
+msgid "Date Modified"
+msgstr "Datum izmjene"
+
+#: qfilesystemmodel_p.h:198
+msgctxt "QFileSystemModel"
+msgid "My Computer"
+msgstr "Moje Računalo"
+
+#: qfilesystemmodel_p.h:200
+msgctxt "QFileSystemModel"
+msgid "Computer"
+msgstr "Računalo"
+
+#: qfilesystemmodel.cpp:677
+msgctxt "QFileSystemModel"
+msgid "%1 TB"
+msgstr "%1 TB"
+
+#: qfilesystemmodel.cpp:679
+msgctxt "QFileSystemModel"
+msgid "%1 GB"
+msgstr "%1 GB"
+
+#: qfilesystemmodel.cpp:681
+msgctxt "QFileSystemModel"
+msgid "%1 MB"
+msgstr "%1 MB"
+
+#: qfilesystemmodel.cpp:683
+msgctxt "QFileSystemModel"
+msgid "%1 KB"
+msgstr "%1 KB"
+
+#: qfilesystemmodel.cpp:684
+msgctxt "QFileSystemModel"
+msgid "%1 bytes"
+msgstr "%1 byteova"
diff --git a/hr_HR/vidalia_hr_HR.po b/hr_HR/vidalia_hr_HR.po
new file mode 100644
index 0000000..4a5ecae
--- /dev/null
+++ b/hr_HR/vidalia_hr_HR.po
@@ -0,0 +1,3847 @@
+#
+# Translators:
+# Armando Vega <synaan(a)gmail.com>, 2012.
+# <trebelnik2(a)gmail.com>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: The Tor Project\n"
+"Report-Msgid-Bugs-To: https://trac.torproject.org/projects/tor\n"
+"POT-Creation-Date: 2012-03-21 17:52+0000\n"
+"PO-Revision-Date: 2012-05-09 08:49+0000\n"
+"Last-Translator: gogo <trebelnik2(a)gmail.com>\n"
+"Language-Team: translations(a)vidalia-project.net\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: hr_HR\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+"X-Generator: Vidalia ts2po 0.2\n"
+
+msgctxt "AboutDialog"
+msgid "About Vidalia"
+msgstr "O Vidalia"
+
+msgctxt "AboutDialog"
+msgid "License"
+msgstr "Licenca"
+
+msgctxt "AboutDialog"
+msgid "Vidalia 0.2.0"
+msgstr "Vidalia 0.2.0"
+
+msgctxt "AboutDialog"
+msgid "Tor 0.2.0.32"
+msgstr "Tor 0.2.0.32"
+
+msgctxt "AboutDialog"
+msgid "Qt 4.4.2"
+msgstr "Qt 4.4.2"
+
+msgctxt "AdvancedPage"
+msgid "'%1' is not a valid IP address."
+msgstr "'%1' nije važeća IP adresa."
+
+msgctxt "AdvancedPage"
+msgid ""
+"You selected 'Password' authentication, but did not specify a password."
+msgstr "Odabrali ste autentifikaciju 'Lozinkom', ali niste postavili lozinku."
+
+msgctxt "AdvancedPage"
+msgid "Select Tor Configuration File"
+msgstr "Odaberi Tor Konfiguracijsku Datoteku"
+
+msgctxt "AdvancedPage"
+msgid "File Not Found"
+msgstr "Datoteka Nije Pronađena"
+
+msgctxt "AdvancedPage"
+msgid "%1 does not exist. Would you like to create it?"
+msgstr "%1 ne postoji. Da li biste ju željeli stvoriti?"
+
+msgctxt "AdvancedPage"
+msgid "Failed to Create File"
+msgstr "Neuspješno Stvaranje Datoteke"
+
+msgctxt "AdvancedPage"
+msgid "Unable to create %1 [%2]"
+msgstr "Nije moguće stvoriti %1 [%2]"
+
+msgctxt "AdvancedPage"
+msgid "Select a Directory to Use for Tor Data"
+msgstr "Odaberite Mapu za Tor Podatke"
+
+msgctxt "AdvancedPage"
+msgid "Unable to remove Tor Service"
+msgstr "Neuspješno uklanjanje Tor Usluge"
+
+msgctxt "AdvancedPage"
+msgid "Unable to install Tor Service"
+msgstr "Neuspješna instalacija Tor Usluge"
+
+msgctxt "AdvancedPage"
+msgid "Vidalia was unable to install the Tor service."
+msgstr "Vidalia nije bila u mogućnosti instalirati Tor uslugu."
+
+msgctxt "AdvancedPage"
+msgid "Authentication:"
+msgstr "Autentifikacija:"
+
+msgctxt "AdvancedPage"
+msgid "Address:"
+msgstr "Adresa:"
+
+msgctxt "AdvancedPage"
+msgid "None"
+msgstr "Ništa"
+
+msgctxt "AdvancedPage"
+msgid "Cookie"
+msgstr "Cookie"
+
+msgctxt "AdvancedPage"
+msgid "Password"
+msgstr "Lozinka"
+
+msgctxt "AdvancedPage"
+msgid "Randomly Generate"
+msgstr "Nasumično Generiraj"
+
+msgctxt "AdvancedPage"
+msgid ":"
+msgstr ":"
+
+msgctxt "AdvancedPage"
+msgid "Tor Configuration File"
+msgstr "Tor Konfiguracijska Datoteka"
+
+msgctxt "AdvancedPage"
+msgid "Start the Tor software with the specified configuration file (torrc)"
+msgstr "Pokreni Tor software sa specificiranom konfiguracijskom datotekom (torrc)"
+
+msgctxt "AdvancedPage"
+msgid "Select path to your configuration file"
+msgstr "Odaberite putanju do vaše konfiguracijske datoteke"
+
+msgctxt "AdvancedPage"
+msgid "Browse"
+msgstr "Pretraži"
+
+msgctxt "AdvancedPage"
+msgid "Data Directory"
+msgstr "Podatkovna Mapa"
+
+msgctxt "AdvancedPage"
+msgid "Store data for the Tor software in the following directory"
+msgstr "Spremaj podatke za Tor software u sljedećoj mapi"
+
+msgctxt "AdvancedPage"
+msgid "Select the directory used to store data for the Tor software"
+msgstr "Odaberite mapu koja će biti korištena za spremanje podataka Tor softwarea"
+
+msgctxt "AdvancedPage"
+msgid "Tor Control"
+msgstr "Tor Upravljanje"
+
+msgctxt "AdvancedPage"
+msgid "Use TCP connection (ControlPort)"
+msgstr "Koristi TCP vezu (KontrolniPort)"
+
+msgctxt "AdvancedPage"
+msgid "Path:"
+msgstr "Putanja:"
+
+msgctxt "AdvancedPage"
+msgid "Use Unix domain socket (ControlSocket)"
+msgstr "Koristi Unix domain socket (KontrolniSocket)"
+
+msgctxt "AdvancedPage"
+msgid "Edit current torrc"
+msgstr "Izmjeni trenutni torrc"
+
+msgctxt "AdvancedPage"
+msgid "NOTE: this will edit the currently loaded torrc"
+msgstr "NAPOMENA: ovo će izmjeniti trenutno učitani torrc"
+
+msgctxt "AdvancedPage"
+msgid "ControlSocket path doesn't exist."
+msgstr "Putanja KontrolnogSocketa ne postoji."
+
+msgctxt "AdvancedPage"
+msgid ""
+"The specified Tor configuration file location contains characters that "
+"cannot be represented in your system's current 8-bit character encoding."
+msgstr "Specificirana lokacija Tor konfiguracijske datoteke sadrži znakove koji se ne mogu koristiti u trenutnom 8 bitnom kodiranju vašeg sustava."
+
+msgctxt "AdvancedPage"
+msgid ""
+"The specified Tor data directory location contains characters that cannot be"
+" represented in your system's current 8-bit character encoding."
+msgstr "Specificirana lokacija Tor podatkovne mape sadrži znakove koji se ne mogu koristiti u trenutnom 8 bitnom kodiranju vašeg sustava."
+
+msgctxt "AdvancedPage"
+msgid "Warning"
+msgstr "Upozorenje"
+
+msgctxt "AdvancedPage"
+msgid "You changed torrc path, would you like to restart Tor?"
+msgstr "Promjenili ste putanju torrc datoteke, želite li ponovno pokrenuti Tor?"
+
+msgctxt "AdvancedPage"
+msgid "Tor Configuration File (torrc);;All Files (*)"
+msgstr "Tor Konfiguracijska Datoteka (torrc);;All Files(*)"
+
+msgctxt "AdvancedPage"
+msgid "Select a file to use for Tor socket path"
+msgstr "Odaberite datoteku za korištenje kao Tor socket putanju"
+
+msgctxt "AdvancedPage"
+msgid "Configure ControlPort automatically"
+msgstr "Automatski podesi KontrolniPort"
+
+msgctxt "AdvancedPage"
+msgid ""
+"You've checked the autoconfiguration option for the ControlPort, but "
+"provided no Data Directory. Please add one, or uncheck the \"Configure "
+"ControlPort automatically\" option."
+msgstr "Odabrali ste mogućnost automatskog podešavanja za Kontrolni ulaz, ali bez direktorija podatka. Dodajte jedan direktorij ili odznačite mogućnost \"Podesi kontrolni ulaz automatski\"."
+
+msgctxt "AdvancedPage"
+msgid ""
+"Vidalia was unable to remove the Tor service.\n"
+"\n"
+"You may need to remove it manually."
+msgstr "Vidalia nije bila u mogućnosti ukloniti Tor uslugu.\n\nMožda ćete ju morati ukloniti ručno."
+
+msgctxt "AppearancePage"
+msgid "Language"
+msgstr "Jezik"
+
+msgctxt "AppearancePage"
+msgid "Choose the language used in Vidalia"
+msgstr "Odaberite jezik korišten u Vidaliji"
+
+msgctxt "AppearancePage"
+msgid "Style"
+msgstr "Stil"
+
+msgctxt "AppearancePage"
+msgid "Choose Vidalia's interface style"
+msgstr "Odaberite Vidalijin stil sučelja"
+
+msgctxt "AppearancePage"
+msgid "Vidalia was unable to load the selected language translation."
+msgstr "Vidalia nije bila u mogućnosti učitati odabrani jezični prijevod."
+
+msgctxt "AppearancePage"
+msgid ""
+"System Icon Preferences (changes will take effect when you restart Vidalia)"
+msgstr "Postavke ikone sustava (izmjene će se primjeniti nakon ponovnog pokretanja Vidalia)"
+
+msgctxt "AppearancePage"
+msgid "Show the Tray Icon and Dock Icon (default)"
+msgstr "Prikaži ikonu obavijesnog područja i ikonu pokretača (uobičajeno)"
+
+msgctxt "AppearancePage"
+msgid "Hide the Tray Icon"
+msgstr "Sakrij ikonu "
+
+msgctxt "AppearancePage"
+msgid "Hide the Dock Icon"
+msgstr "Sakrij ikonu pokretača"
+
+msgctxt "BandwidthGraph"
+msgid "Since:"
+msgstr "Od:"
+
+msgctxt "BandwidthGraph"
+msgid "Hide Settings"
+msgstr "Sakrij Postavke"
+
+msgctxt "BandwidthGraph"
+msgid "Show Settings"
+msgstr "Prikaži Postavke"
+
+msgctxt "BandwidthGraph"
+msgid "Tor Bandwidth Usage"
+msgstr "Tor Korištenje Propusnosti"
+
+msgctxt "BandwidthGraph"
+msgid "Reset"
+msgstr "Reset"
+
+msgctxt "BandwidthGraph"
+msgid "Receive Rate"
+msgstr "Brzina Primanja"
+
+msgctxt "BandwidthGraph"
+msgid "Send Rate"
+msgstr "Brzina Slanja"
+
+msgctxt "BandwidthGraph"
+msgid "Always on Top"
+msgstr "Uvijek na Vrhu"
+
+msgctxt "BandwidthGraph"
+msgid "Style"
+msgstr "Stil"
+
+msgctxt "BandwidthGraph"
+msgid "Changes the transparency of the Bandwidth Graph"
+msgstr "Mijenja transparenciju Grafa Propusnosti"
+
+msgctxt "BandwidthGraph"
+msgid "100"
+msgstr "100"
+
+msgctxt "BandwidthGraph"
+msgid "% Opaque"
+msgstr "% Neproziran"
+
+msgctxt "BandwidthGraph"
+msgid "Save"
+msgstr "Spremi"
+
+msgctxt "BandwidthGraph"
+msgid "Cancel"
+msgstr "Odustani"
+
+msgctxt "BridgeDownloader"
+msgid "Starting HTTPS bridge request..."
+msgstr "Započinjem zahtjev za HTTPS mostom..."
+
+msgctxt "BridgeDownloader"
+msgid "Connecting to %1:%2..."
+msgstr "Spajanje na %1:%2..."
+
+msgctxt "BridgeDownloader"
+msgid "Sending an HTTPS request for bridges..."
+msgstr "Slanje HTTPS zahtjeva za mostovima..."
+
+msgctxt "BridgeDownloader"
+msgid "Downloading a list of bridges..."
+msgstr "Preuzimanje popisa mostova..."
+
+msgctxt "BridgeDownloaderProgressDialog"
+msgid "Downloading Bridges"
+msgstr "Preuzimanje Mostova"
+
+msgctxt "BridgeDownloaderProgressDialog"
+msgid "Unable to download bridges: %1"
+msgstr "Nije moguće preuzeti mostove: %1"
+
+msgctxt "BridgeDownloaderProgressDialog"
+msgid "Retrying bridge request..."
+msgstr "Ponovni pokušaj zahtjeva za mostom..."
+
+msgctxt "BridgeUsageDialog"
+msgid "Country"
+msgstr "Država"
+
+msgctxt "BridgeUsageDialog"
+msgid "# Clients"
+msgstr "# Klijenti"
+
+msgctxt "BridgeUsageDialog"
+msgid "Clients from the following countries have used your relay since %1"
+msgstr "Klijenti iz sljedećih država su koristili vaš relej od %1"
+
+msgctxt "BridgeUsageDialog"
+msgid "Bridge Usage Summary"
+msgstr "Sažetak Korištenja Mosta"
+
+msgctxt "BridgeUsageDialog"
+msgid "Client Summary"
+msgstr "Sažetak Klijenata"
+
+msgctxt "Circuit"
+msgid "New"
+msgstr "Novo"
+
+msgctxt "Circuit"
+msgid "Open"
+msgstr "Otvori"
+
+msgctxt "Circuit"
+msgid "Building"
+msgstr "Građenje"
+
+msgctxt "Circuit"
+msgid "Failed"
+msgstr "Neuspjelo"
+
+msgctxt "Circuit"
+msgid "Closed"
+msgstr "Zatvoreno"
+
+msgctxt "Circuit"
+msgid "Unknown"
+msgstr "Nepoznato"
+
+msgctxt "CircuitItem"
+msgid "<Path Empty>"
+msgstr "<Putanja Prazna>"
+
+msgctxt "CircuitListWidget"
+msgid "Connection"
+msgstr "Veza"
+
+msgctxt "CircuitListWidget"
+msgid "Status"
+msgstr "Status"
+
+msgctxt "CircuitListWidget"
+msgid "Zoom to Circuit"
+msgstr "Uvećaj prema Krugu"
+
+msgctxt "CircuitListWidget"
+msgid "Close Circuit (Del)"
+msgstr "Zatvori Krug (Del)"
+
+msgctxt "CircuitListWidget"
+msgid "Close Stream (Del)"
+msgstr "Zatvori Tok (Del)"
+
+msgctxt "ConfigDialog"
+msgid "General"
+msgstr "Općenito"
+
+msgctxt "ConfigDialog"
+msgid "Network"
+msgstr "Mreža"
+
+msgctxt "ConfigDialog"
+msgid "Sharing"
+msgstr "Dijeljenje"
+
+msgctxt "ConfigDialog"
+msgid "Services"
+msgstr "Usluge"
+
+msgctxt "ConfigDialog"
+msgid "Appearance"
+msgstr "Izgled"
+
+msgctxt "ConfigDialog"
+msgid "Advanced"
+msgstr "Napredno"
+
+msgctxt "ConfigDialog"
+msgid "Help"
+msgstr "Pomoć"
+
+msgctxt "ConfigDialog"
+msgid "Error Saving Settings"
+msgstr "Greška pri Spremanju Postavki"
+
+msgctxt "ConfigDialog"
+msgid "Vidalia was unable to save your %1 settings."
+msgstr "Vidalia nije bila u mogućnosti spremiti vaše %1 postavke."
+
+msgctxt "ConfigDialog"
+msgid "Error Applying Settings"
+msgstr "Greška pri Primjenjivanju Postavki"
+
+msgctxt "ConfigDialog"
+msgid "Vidalia was unable to apply your %1 settings to Tor."
+msgstr "Vidalia nije bila u mogućnosti primjeniti vaše %1 postavke za Tor."
+
+msgctxt "ConfigDialog"
+msgid "Settings"
+msgstr "Postavke"
+
+msgctxt "ControlConnection"
+msgid "Vidalia was unable to connect to Tor. (%1)"
+msgstr "Vidalia nije bila u mogućnosti spojiti se na Tor. (%1)"
+
+msgctxt "ControlConnection"
+msgid "Control socket is not connected."
+msgstr "Kontrolni socket nije spojen."
+
+msgctxt "ControlPasswordInputDialog"
+msgid "Password Required"
+msgstr "Potrebna Lozinka"
+
+msgctxt "ControlPasswordInputDialog"
+msgid "Remember my password"
+msgstr "Zapamti moju lozinku"
+
+msgctxt "ControlPasswordInputDialog"
+msgid ""
+"Vidalia has connected to a running Tor process that requires a password. "
+"Please enter your control password:"
+msgstr "Vidalia se spojila na pokrenuti Tor proces koji zahtjeva lozinku. Molimo unesite svoju kontrolnu lozinku:"
+
+msgctxt "ControlSocket"
+msgid "Control socket is not connected."
+msgstr "Kontrolni socket nije spojen."
+
+msgctxt "ControlSocket"
+msgid "Error sending control command. [%1]"
+msgstr "Greška pri slanju kontrolne naredbe. [%1]"
+
+msgctxt "ControlSocket"
+msgid "Socket disconnected while attempting to read a line of data."
+msgstr "Socket se odspojio tijekom pokušaja čitanja linije podataka."
+
+msgctxt "ControlSocket"
+msgid "Invalid control reply. [%1]"
+msgstr "Nevažeći kontrolni odgovor. [%1]"
+
+msgctxt "CountryInfo"
+msgid "Afghanistan"
+msgstr "Afganistan"
+
+msgctxt "CountryInfo"
+msgid "Andorra"
+msgstr "Andora"
+
+msgctxt "CountryInfo"
+msgid "Angola"
+msgstr "Angola"
+
+msgctxt "CountryInfo"
+msgid "Antigua & Barbuda"
+msgstr "Antigua & Barbuda"
+
+msgctxt "CountryInfo"
+msgid "Argentina"
+msgstr "Argentina"
+
+msgctxt "CountryInfo"
+msgid "Armenia"
+msgstr "Armenija"
+
+msgctxt "CountryInfo"
+msgid "Australia"
+msgstr "Australija"
+
+msgctxt "CountryInfo"
+msgid "Azerbaijan"
+msgstr "Azerbedžan"
+
+msgctxt "CountryInfo"
+msgid "Bahamas"
+msgstr "Bahami"
+
+msgctxt "CountryInfo"
+msgid "Bangladesh"
+msgstr "Bangladeš"
+
+msgctxt "CountryInfo"
+msgid "Barbados"
+msgstr "Barbados"
+
+msgctxt "CountryInfo"
+msgid "Belarus"
+msgstr "Bjelorusija"
+
+msgctxt "CountryInfo"
+msgid "Belgium"
+msgstr "Belgija"
+
+msgctxt "CountryInfo"
+msgid "Belize"
+msgstr "Belize"
+
+msgctxt "CountryInfo"
+msgid "Bhutan"
+msgstr "Butan"
+
+msgctxt "CountryInfo"
+msgid "Bolivia"
+msgstr "Bolivija"
+
+msgctxt "CountryInfo"
+msgid "Bosnia & Herzegovina"
+msgstr "Bosna i Hercegovina"
+
+msgctxt "CountryInfo"
+msgid "Botswana"
+msgstr "Bocvana"
+
+msgctxt "CountryInfo"
+msgid "Brazil"
+msgstr "Brazil"
+
+msgctxt "CountryInfo"
+msgid "Brunei Darussalam"
+msgstr "Brunei Darussalam"
+
+msgctxt "CountryInfo"
+msgid "Bulgaria"
+msgstr "Bugarska"
+
+msgctxt "CountryInfo"
+msgid "Burkina Faso"
+msgstr "Burkina Faso"
+
+msgctxt "CountryInfo"
+msgid "Burundi"
+msgstr "Burundi"
+
+msgctxt "CountryInfo"
+msgid "Cambodia"
+msgstr "Kambodža"
+
+msgctxt "CountryInfo"
+msgid "Cameroon"
+msgstr "Kamerun"
+
+msgctxt "CountryInfo"
+msgid "Canada"
+msgstr "Kanada"
+
+msgctxt "CountryInfo"
+msgid "Cape Verde"
+msgstr "Cape Verde"
+
+msgctxt "CountryInfo"
+msgid "Central African Republic"
+msgstr "Centralna Afrička Republika"
+
+msgctxt "CountryInfo"
+msgid "Chad"
+msgstr "Čad"
+
+msgctxt "CountryInfo"
+msgid "Chile"
+msgstr "Čile"
+
+msgctxt "CountryInfo"
+msgid "China"
+msgstr "Kina"
+
+msgctxt "CountryInfo"
+msgid "Colombia"
+msgstr "Kolumbija"
+
+msgctxt "CountryInfo"
+msgid "Comoros"
+msgstr "Comoros"
+
+msgctxt "CountryInfo"
+msgid "Congo, The Democratic Republic of the"
+msgstr "Kongo, Demokratska Republika"
+
+msgctxt "CountryInfo"
+msgid "Congo"
+msgstr "Kongo"
+
+msgctxt "CountryInfo"
+msgid "Costa Rica"
+msgstr "Kostarika"
+
+msgctxt "CountryInfo"
+msgid "Cote dâIvoire"
+msgstr "Obala Bjelokosti"
+
+msgctxt "CountryInfo"
+msgid "Croatia"
+msgstr "Hrvatska"
+
+msgctxt "CountryInfo"
+msgid "Cuba"
+msgstr "Kuba"
+
+msgctxt "CountryInfo"
+msgid "Cyprus"
+msgstr "Cipar"
+
+msgctxt "CountryInfo"
+msgid "Czech Republic"
+msgstr "Češka Republika"
+
+msgctxt "CountryInfo"
+msgid "Denmark"
+msgstr "Danska"
+
+msgctxt "CountryInfo"
+msgid "Djibouti"
+msgstr "Djibouti"
+
+msgctxt "CountryInfo"
+msgid "Dominica"
+msgstr "Dominica"
+
+msgctxt "CountryInfo"
+msgid "Dominican Republic"
+msgstr "Dominikanska Republika"
+
+msgctxt "CountryInfo"
+msgid "Ecuador"
+msgstr "Ekvador"
+
+msgctxt "CountryInfo"
+msgid "Egypt"
+msgstr "Egipat"
+
+msgctxt "CountryInfo"
+msgid "El Salvador"
+msgstr "El Salvador"
+
+msgctxt "CountryInfo"
+msgid "Equatorial Guinea"
+msgstr "Ekvatorijalna Gvineja"
+
+msgctxt "CountryInfo"
+msgid "Eritrea"
+msgstr "Eritreja"
+
+msgctxt "CountryInfo"
+msgid "Estonia"
+msgstr "Estonija"
+
+msgctxt "CountryInfo"
+msgid "France"
+msgstr "Francuska"
+
+msgctxt "CountryInfo"
+msgid "Gabon"
+msgstr "Gabon"
+
+msgctxt "CountryInfo"
+msgid "Gambia"
+msgstr "Gambia"
+
+msgctxt "CountryInfo"
+msgid "Georgia"
+msgstr "Gruzija"
+
+msgctxt "CountryInfo"
+msgid "Germany"
+msgstr "Njemačka"
+
+msgctxt "CountryInfo"
+msgid "Ghana"
+msgstr "Gana"
+
+msgctxt "CountryInfo"
+msgid "Grenada"
+msgstr "Grenada"
+
+msgctxt "CountryInfo"
+msgid "Guatemala"
+msgstr "Gvatemala"
+
+msgctxt "CountryInfo"
+msgid "Guinea"
+msgstr "Gvineja"
+
+msgctxt "CountryInfo"
+msgid "Guinea-Bissau"
+msgstr "Gvineja-Bissau"
+
+msgctxt "CountryInfo"
+msgid "Guyana"
+msgstr "Guyana"
+
+msgctxt "CountryInfo"
+msgid "Hong Kong"
+msgstr "Hong Kong"
+
+msgctxt "CountryInfo"
+msgid "Haiti"
+msgstr "Haiti"
+
+msgctxt "CountryInfo"
+msgid "Honduras"
+msgstr "Honduras"
+
+msgctxt "CountryInfo"
+msgid "Israel"
+msgstr "Izrael"
+
+msgctxt "CountryInfo"
+msgid "Italy"
+msgstr "Italija"
+
+msgctxt "CountryInfo"
+msgid "Jamaica"
+msgstr "Jamajka"
+
+msgctxt "CountryInfo"
+msgid "Japan"
+msgstr "Japan"
+
+msgctxt "CountryInfo"
+msgid "Jordan"
+msgstr "Jordan"
+
+msgctxt "CountryInfo"
+msgid "Kazakhstan"
+msgstr "Kazahstan"
+
+msgctxt "CountryInfo"
+msgid "Kenya"
+msgstr "Kenija"
+
+msgctxt "CountryInfo"
+msgid "Kiribati"
+msgstr "Kiribati"
+
+msgctxt "CountryInfo"
+msgid "Kuwait"
+msgstr "Kuvajt"
+
+msgctxt "CountryInfo"
+msgid "Kyrgyzstan"
+msgstr "Kirgistan"
+
+msgctxt "CountryInfo"
+msgid "Laos"
+msgstr "Laos"
+
+msgctxt "CountryInfo"
+msgid "Latvia"
+msgstr "Latvija"
+
+msgctxt "CountryInfo"
+msgid "Lebanon"
+msgstr "Libanon"
+
+msgctxt "CountryInfo"
+msgid "Lesotho"
+msgstr "Lesoto"
+
+msgctxt "CountryInfo"
+msgid "Liberia"
+msgstr "Liberija"
+
+msgctxt "CountryInfo"
+msgid "Liechtenstein"
+msgstr "Lihtenštajn"
+
+msgctxt "CountryInfo"
+msgid "Lithuania"
+msgstr "Litva"
+
+msgctxt "CountryInfo"
+msgid "Luxembourg"
+msgstr "Luksemburg"
+
+msgctxt "CountryInfo"
+msgid "Macedonia"
+msgstr "Makedonija"
+
+msgctxt "CountryInfo"
+msgid "Madagascar"
+msgstr "Madagaskar"
+
+msgctxt "CountryInfo"
+msgid "Malawi"
+msgstr "Malawi"
+
+msgctxt "CountryInfo"
+msgid "Malaysia"
+msgstr "Malezija"
+
+msgctxt "CountryInfo"
+msgid "Mali"
+msgstr "Mali"
+
+msgctxt "CountryInfo"
+msgid "Malta"
+msgstr "Malta"
+
+msgctxt "CountryInfo"
+msgid "Marshall Islands"
+msgstr "Maršalovi Otoci"
+
+msgctxt "CountryInfo"
+msgid "Mauritania"
+msgstr "Mauritanija"
+
+msgctxt "CountryInfo"
+msgid "Mauritius"
+msgstr "Mauricijus"
+
+msgctxt "CountryInfo"
+msgid "Micronesia"
+msgstr "Mikronezija"
+
+msgctxt "CountryInfo"
+msgid "Moldova"
+msgstr "Moldavija"
+
+msgctxt "CountryInfo"
+msgid "Monaco"
+msgstr "Monako"
+
+msgctxt "CountryInfo"
+msgid "Mongolia"
+msgstr "Mongolia"
+
+msgctxt "CountryInfo"
+msgid "Montenegro"
+msgstr "Crna Gora"
+
+msgctxt "CountryInfo"
+msgid "Morocco"
+msgstr "Maroko"
+
+msgctxt "CountryInfo"
+msgid "Mozambique"
+msgstr "Mozambik"
+
+msgctxt "CountryInfo"
+msgid "Namibia"
+msgstr "Namibija"
+
+msgctxt "CountryInfo"
+msgid "Nauru"
+msgstr "Nauru"
+
+msgctxt "CountryInfo"
+msgid "Nepal"
+msgstr "Nepal"
+
+msgctxt "CountryInfo"
+msgid "Netherlands"
+msgstr "Nizozemska"
+
+msgctxt "CountryInfo"
+msgid "New Zealand"
+msgstr "Novi Zeland"
+
+msgctxt "CountryInfo"
+msgid "Nicaragua"
+msgstr "Nikaragva"
+
+msgctxt "CountryInfo"
+msgid "Niger"
+msgstr "Niger"
+
+msgctxt "CountryInfo"
+msgid "Nigeria"
+msgstr "Nigerija"
+
+msgctxt "CountryInfo"
+msgid "Norway"
+msgstr "Norveška"
+
+msgctxt "CountryInfo"
+msgid "Oman"
+msgstr "Oman"
+
+msgctxt "CountryInfo"
+msgid "Pakistan"
+msgstr "Pakistan"
+
+msgctxt "CountryInfo"
+msgid "Palau"
+msgstr "Palau"
+
+msgctxt "CountryInfo"
+msgid "Palestine"
+msgstr "Palestina"
+
+msgctxt "CountryInfo"
+msgid "Panama"
+msgstr "Panama"
+
+msgctxt "CountryInfo"
+msgid "Papua New Guinea"
+msgstr "Papua Nova Gvineja"
+
+msgctxt "CountryInfo"
+msgid "Paraguay"
+msgstr "Paragvaj"
+
+msgctxt "CountryInfo"
+msgid "Peru"
+msgstr "Peru"
+
+msgctxt "CountryInfo"
+msgid "Philippines"
+msgstr "Filipini"
+
+msgctxt "CountryInfo"
+msgid "Poland"
+msgstr "Poljska"
+
+msgctxt "CountryInfo"
+msgid "Portugal"
+msgstr "Portugal"
+
+msgctxt "CountryInfo"
+msgid "Qatar"
+msgstr "Katar"
+
+msgctxt "CountryInfo"
+msgid "Romania"
+msgstr "Rumunjska"
+
+msgctxt "CountryInfo"
+msgid "Russia"
+msgstr "Rusija"
+
+msgctxt "CountryInfo"
+msgid "Rwanda"
+msgstr "Ruanda"
+
+msgctxt "CountryInfo"
+msgid "Saint Kitts & Nevis"
+msgstr "Saint Kitts & Nevis"
+
+msgctxt "CountryInfo"
+msgid "Saint Lucia"
+msgstr "Saint Lucia"
+
+msgctxt "CountryInfo"
+msgid "Saint Vincent & the Grenadines"
+msgstr "Saint Vincent & the Grenadines"
+
+msgctxt "CountryInfo"
+msgid "Samoa"
+msgstr "Samoa"
+
+msgctxt "CountryInfo"
+msgid "San Marino"
+msgstr "San Marino"
+
+msgctxt "CountryInfo"
+msgid "Sao Tome & Principe"
+msgstr "Sao Tome & Principe"
+
+msgctxt "CountryInfo"
+msgid "Saudi Arabia"
+msgstr "Saudijska Arabija"
+
+msgctxt "CountryInfo"
+msgid "Senegal"
+msgstr "Senegal"
+
+msgctxt "CountryInfo"
+msgid "Serbia"
+msgstr "Srbija"
+
+msgctxt "CountryInfo"
+msgid "Seychelles"
+msgstr "Sejšeli"
+
+msgctxt "CountryInfo"
+msgid "Sierra Leone"
+msgstr "Sierra Leone"
+
+msgctxt "CountryInfo"
+msgid "Singapore"
+msgstr "Singapur"
+
+msgctxt "CountryInfo"
+msgid "Slovakia"
+msgstr "Slovačka"
+
+msgctxt "CountryInfo"
+msgid "Slovenia"
+msgstr "Slovenija"
+
+msgctxt "CountryInfo"
+msgid "Solomon Islands"
+msgstr "Solomonski Otoci"
+
+msgctxt "CountryInfo"
+msgid "Somalia"
+msgstr "Somalija"
+
+msgctxt "CountryInfo"
+msgid "South Africa"
+msgstr "Južna Afrika"
+
+msgctxt "CountryInfo"
+msgid "Spain"
+msgstr "Španjolska"
+
+msgctxt "CountryInfo"
+msgid "Sri Lanka"
+msgstr "Sri Lanka"
+
+msgctxt "CountryInfo"
+msgid "Sudan"
+msgstr "Sudan"
+
+msgctxt "CountryInfo"
+msgid "Suriname"
+msgstr "Suriname"
+
+msgctxt "CountryInfo"
+msgid "Swaziland"
+msgstr "Swaziland"
+
+msgctxt "CountryInfo"
+msgid "Sweden"
+msgstr "Švedska"
+
+msgctxt "CountryInfo"
+msgid "Switzerland"
+msgstr "Švicarska"
+
+msgctxt "CountryInfo"
+msgid "Syria"
+msgstr "Sirija"
+
+msgctxt "CountryInfo"
+msgid "Tajikistan"
+msgstr "Tadžikistan"
+
+msgctxt "CountryInfo"
+msgid "Tanzania"
+msgstr "Tanzanija"
+
+msgctxt "CountryInfo"
+msgid "Thailand"
+msgstr "Tajland"
+
+msgctxt "CountryInfo"
+msgid "Timor-Leste (East Timor)"
+msgstr "Timor-Leste (Istočni Timor)"
+
+msgctxt "CountryInfo"
+msgid "Togo"
+msgstr "Togo"
+
+msgctxt "CountryInfo"
+msgid "Tonga"
+msgstr "Tonga"
+
+msgctxt "CountryInfo"
+msgid "Trinidad & Tobago"
+msgstr "Trinidad i Tobago"
+
+msgctxt "CountryInfo"
+msgid "Tunisia"
+msgstr "Tunis"
+
+msgctxt "CountryInfo"
+msgid "Turkey"
+msgstr "Turska"
+
+msgctxt "CountryInfo"
+msgid "Turkmenistan"
+msgstr "Turkmenistan"
+
+msgctxt "CountryInfo"
+msgid "Tuvalu"
+msgstr "Tuvalu"
+
+msgctxt "CountryInfo"
+msgid "Uganda"
+msgstr "Uganda"
+
+msgctxt "CountryInfo"
+msgid "Ukraine"
+msgstr "Ukrajina"
+
+msgctxt "CountryInfo"
+msgid "United Arab Emirates"
+msgstr "Ujedinjeni Arapski Emirati"
+
+msgctxt "CountryInfo"
+msgid "United Kingdom"
+msgstr "Ujedinjeno Kraljevstvo"
+
+msgctxt "CountryInfo"
+msgid "United States"
+msgstr "Sjedinjene Američke Države"
+
+msgctxt "CountryInfo"
+msgid "Uruguay"
+msgstr "Urugvaj"
+
+msgctxt "CountryInfo"
+msgid "Uzbekistan"
+msgstr "Uzbekistan"
+
+msgctxt "CountryInfo"
+msgid "Vanuatu"
+msgstr "Vanuatu"
+
+msgctxt "CountryInfo"
+msgid "Vatican"
+msgstr "Vatikan"
+
+msgctxt "CountryInfo"
+msgid "Venezuela"
+msgstr "Venecuela"
+
+msgctxt "CountryInfo"
+msgid "Vietnam"
+msgstr "Vijetnam"
+
+msgctxt "CountryInfo"
+msgid "Western Sahara"
+msgstr "Zapadna Sahara"
+
+msgctxt "CountryInfo"
+msgid "Yemen"
+msgstr "Jemen"
+
+msgctxt "CountryInfo"
+msgid "Zambia"
+msgstr "Zambia"
+
+msgctxt "CountryInfo"
+msgid "Zimbabwe"
+msgstr "Zimbabve"
+
+msgctxt "CountryInfo"
+msgid "Zaire"
+msgstr "Zaire"
+
+msgctxt "CountryInfo"
+msgid "Albania"
+msgstr "Albanija"
+
+msgctxt "CountryInfo"
+msgid "Algeria"
+msgstr "Alžir"
+
+msgctxt "CountryInfo"
+msgid "Austria"
+msgstr "Austrija"
+
+msgctxt "CountryInfo"
+msgid "Bahrain"
+msgstr "Bahrejn"
+
+msgctxt "CountryInfo"
+msgid "Benin"
+msgstr "Benin"
+
+msgctxt "CountryInfo"
+msgid "Ethiopia"
+msgstr "Etiopija"
+
+msgctxt "CountryInfo"
+msgid "Fiji"
+msgstr "Fidži"
+
+msgctxt "CountryInfo"
+msgid "Finland"
+msgstr "Finska"
+
+msgctxt "CountryInfo"
+msgid "Greece"
+msgstr "Grčka"
+
+msgctxt "CountryInfo"
+msgid "Guam"
+msgstr "Guam"
+
+msgctxt "CountryInfo"
+msgid "Hungary"
+msgstr "Mađarska"
+
+msgctxt "CountryInfo"
+msgid "Iceland"
+msgstr "Island"
+
+msgctxt "CountryInfo"
+msgid "India"
+msgstr "Indija"
+
+msgctxt "CountryInfo"
+msgid "Indonesia"
+msgstr "Indonezija"
+
+msgctxt "CountryInfo"
+msgid "Iran"
+msgstr "Iran"
+
+msgctxt "CountryInfo"
+msgid "Iraq"
+msgstr "Irak"
+
+msgctxt "CountryInfo"
+msgid "Ireland"
+msgstr "Irska"
+
+msgctxt "CountryInfo"
+msgid "Korea, North"
+msgstr "Koreja, Sjeverna"
+
+msgctxt "CountryInfo"
+msgid "Korea, South"
+msgstr "Koreja, Južna"
+
+msgctxt "CountryInfo"
+msgid "Libya"
+msgstr "Libija"
+
+msgctxt "CountryInfo"
+msgid "Maldives"
+msgstr "Maldivi"
+
+msgctxt "CountryInfo"
+msgid "Mexico"
+msgstr "Meksiko"
+
+msgctxt "CountryInfo"
+msgid "Myanmar"
+msgstr "Mijanmar"
+
+msgctxt "CountryInfo"
+msgid "Taiwan"
+msgstr "Tajvan"
+
+msgctxt "CrashReportDialog"
+msgid "Submit a Crash Report"
+msgstr "Predaj Izvještaj o Rušenju"
+
+msgctxt "CrashReportDialog"
+msgid "Vidalia encountered an error and needed to close"
+msgstr "Vidalia je naišla na grešku i treba se zatvoriti"
+
+msgctxt "CrashReportDialog"
+msgid "Restart Vidalia"
+msgstr "Ponovno Pokreni Vidaliu"
+
+msgctxt "CrashReportDialog"
+msgid "Don't Restart"
+msgstr "Ne Pokreći Ponovno"
+
+msgctxt "CrashReportDialog"
+msgid "Unable to restart Vidalia"
+msgstr "Nije bilo moguće ponovno pokrenuti Vidaliu"
+
+msgctxt "CrashReportDialog"
+msgid ""
+"We were unable to automatically restart Vidalia. Please restart Vidalia "
+"manually."
+msgstr "Nismo bili u mogućnosti automatski ponovno pokrenuti Vidaliu. Molimo pokrenite ponovno Vidaliu ručno."
+
+msgctxt "CrashReportDialog"
+msgid "Please fill a ticket in:"
+msgstr "Molimo unesite tiket:"
+
+msgctxt "CrashReportDialog"
+msgid ""
+"<a "
+"href=\"https://trac.torproject.org/projects/tor/newticket\">https://trac.torproject.org/projects/tor/newticket</a>"
+msgstr "<a href=\"https://trac.torproject.org/projects/tor/newticket\">https://trac.torproject.org/projects/tor/newticket</a>"
+
+msgctxt "CrashReportDialog"
+msgid ""
+"A crash report has been created that you can send to the Vidalia developers "
+"to help identify and fix the problem. The submitted report does not contain "
+"any personally identifying information."
+msgstr "Kreirano je izvješće o rušenju koje možete poslati developerima Vidalie kako biste pomogli identificirati i riješiti problem. Podnesena prijava ne sadrži nikakve osobne identifikacijske podatke."
+
+msgctxt "CrashReportDialog"
+msgid ""
+"with a description of what you were doing before the application crashed, "
+"along with the following files corresponding to the crash report:"
+msgstr "sa opisom što se tradili prije no što se aplikacija srušila, zajedno sa sljedećim datotekama vezanim uz izvješće o rušenju:"
+
+msgctxt "GeneralPage"
+msgid "Executables (*.exe)"
+msgstr "Izvršne datoteke (*.exe)"
+
+msgctxt "GeneralPage"
+msgid "Select Path to Tor"
+msgstr "Odaberite Putanju do Tora"
+
+msgctxt "GeneralPage"
+msgid "Select Proxy Executable"
+msgstr "Odaberite Proxy Izvršnu Datoteku"
+
+msgctxt "GeneralPage"
+msgid "You must specify the name of your Tor executable."
+msgstr "Morate specificirati ime vaše Tor izvršne datoteke."
+
+msgctxt "GeneralPage"
+msgid "Start Vidalia when my system starts"
+msgstr "Pokreni Vidaliu pri pokretanju sustava"
+
+msgctxt "GeneralPage"
+msgid "Browse"
+msgstr "Pretraži"
+
+msgctxt "GeneralPage"
+msgid "Start the Tor software when Vidalia starts"
+msgstr "Pokreni Tor software pri pokretanju Vidalie"
+
+msgctxt "GeneralPage"
+msgid "Tor"
+msgstr "Tor"
+
+msgctxt "GeneralPage"
+msgid "Proxy Application (optional)"
+msgstr "Proxy Aplikacija (opcionalno)"
+
+msgctxt "GeneralPage"
+msgid "Start a proxy application when Tor starts"
+msgstr "Pokreni proxy aplikaciju kada se Tor pokrene"
+
+msgctxt "GeneralPage"
+msgid "Proxy Application Arguments:"
+msgstr "Parametri Proxy Aplikacije:"
+
+msgctxt "GeneralPage"
+msgid "Software Updates"
+msgstr "Ažuriranje Softwarea"
+
+msgctxt "GeneralPage"
+msgid "Check for new software updates automatically"
+msgstr "Automatski provjeravaj za ažuriranje softwarea"
+
+msgctxt "GeneralPage"
+msgid "Check Now"
+msgstr "Provjeri Sada"
+
+msgctxt "GraphFrame"
+msgid "%1 KB/s"
+msgstr "%1 KB/s"
+
+msgctxt "GraphFrame"
+msgid "%1 KB"
+msgstr "%1 KB"
+
+msgctxt "GraphFrame"
+msgid "%1 MB"
+msgstr "%1 MB"
+
+msgctxt "GraphFrame"
+msgid "%1 GB"
+msgstr "%1 GB"
+
+msgctxt "GraphFrame"
+msgid "Recv:"
+msgstr "Prim:"
+
+msgctxt "GraphFrame"
+msgid "Sent:"
+msgstr "Posl:"
+
+msgctxt "HelpBrowser"
+msgid "Supplied XML file is not a valid Contents document."
+msgstr "Data XML datoteka nije važeći dokument Sadržaja"
+
+msgctxt "HelpBrowser"
+msgid "Search reached end of document"
+msgstr "Pretraga je došla do kraja dokumenta"
+
+msgctxt "HelpBrowser"
+msgid "Search reached start of document"
+msgstr "Pretraga je došla do početka dokumenta"
+
+msgctxt "HelpBrowser"
+msgid "Text not found in document"
+msgstr "Tekst nije pronađen u dokumentu"
+
+msgctxt "HelpBrowser"
+msgid "Found %1 results"
+msgstr "Pronađeno %1 rezultata"
+
+msgctxt "HelpBrowser"
+msgid "Vidalia Help"
+msgstr "Vidalia Pomoć"
+
+msgctxt "HelpBrowser"
+msgid "Back"
+msgstr "Natrag"
+
+msgctxt "HelpBrowser"
+msgid "Move to previous page (Backspace)"
+msgstr "Povratak na prethodnu stranicu (Backspace)"
+
+msgctxt "HelpBrowser"
+msgid "Backspace"
+msgstr "Backspace"
+
+msgctxt "HelpBrowser"
+msgid "Forward"
+msgstr "Naprijed"
+
+msgctxt "HelpBrowser"
+msgid "Move to next page (Shift+Backspace)"
+msgstr "Pomicanje na sljedeću stranicu (Shift+Backspace)"
+
+msgctxt "HelpBrowser"
+msgid "Shift+Backspace"
+msgstr "Shift+Backspace"
+
+msgctxt "HelpBrowser"
+msgid "Home"
+msgstr "Home"
+
+msgctxt "HelpBrowser"
+msgid "Move to the Home page (Ctrl+H)"
+msgstr "Povratak na domaću stranicu (Ctrl+H)"
+
+msgctxt "HelpBrowser"
+msgid "Ctrl+H"
+msgstr "Ctrl+H"
+
+msgctxt "HelpBrowser"
+msgid "Find"
+msgstr "Pronađi"
+
+msgctxt "HelpBrowser"
+msgid "Search for a word or phrase on current page (Ctrl+F)"
+msgstr "Pretraga za riječ ili frazu na trenutnoj stranici (Ctrl+F)"
+
+msgctxt "HelpBrowser"
+msgid "Ctrl+F"
+msgstr "Ctrl+F"
+
+msgctxt "HelpBrowser"
+msgid "Close"
+msgstr "Zatvori"
+
+msgctxt "HelpBrowser"
+msgid "Close Vidalia Help"
+msgstr "Zatvori Vidalia Pomoć"
+
+msgctxt "HelpBrowser"
+msgid "Esc"
+msgstr "Esc"
+
+msgctxt "HelpBrowser"
+msgid "Find:"
+msgstr "Pronađi:"
+
+msgctxt "HelpBrowser"
+msgid "Find Previous"
+msgstr "Pronađi prethodno"
+
+msgctxt "HelpBrowser"
+msgid "Find Next"
+msgstr "Pronađi sljedeće"
+
+msgctxt "HelpBrowser"
+msgid "Case sensitive"
+msgstr "Osjetljiv na veličinu slova"
+
+msgctxt "HelpBrowser"
+msgid "Whole words only"
+msgstr "Samo cijele riječi"
+
+msgctxt "HelpBrowser"
+msgid "Help Topics"
+msgstr "Teme Pomoći"
+
+msgctxt "HelpBrowser"
+msgid "Contents"
+msgstr "Sadržaj"
+
+msgctxt "HelpBrowser"
+msgid "Search"
+msgstr "Pretraživanje"
+
+msgctxt "HelpBrowser"
+msgid "Searching for:"
+msgstr "Pretražujem za:"
+
+msgctxt "HelpBrowser"
+msgid "Found Documents"
+msgstr "Pronađeni Dokumenti"
+
+msgctxt "HelpBrowser"
+msgid "Error Loading Help Contents:"
+msgstr "Greška pri Učitavanju Sadržaja Pomoći:"
+
+msgctxt "HelpTextBrowser"
+msgid "Opening External Link"
+msgstr "Otvaranje Vanjske Poveznice"
+
+msgctxt "HelpTextBrowser"
+msgid ""
+"Vidalia can open the link you selected in your default Web browser. If your "
+"browser is not currently configured to use Tor then the request will not be "
+"anonymous."
+msgstr "Vidalia može otvoriti poveznicu koju ste odabrali u vašem pretpostavljenom Web pregledniku. Ako vaš preglednik nije trenutno podešen za korištenje Tora onda zahtjev neće biti anoniman."
+
+msgctxt "HelpTextBrowser"
+msgid "Do you want Vidalia to open the link in your Web browser?"
+msgstr "Želite li da VIdalia otvori poveznicu u vašem Web pregledniku?"
+
+msgctxt "HelpTextBrowser"
+msgid "Unable to Open Link"
+msgstr "Nije Bilo Boguće Otvoriti Poveznicu"
+
+msgctxt "HelpTextBrowser"
+msgid ""
+"Vidalia was unable to open the selected link in your Web browser. You can "
+"still copy the URL and paste it into your browser."
+msgstr "Vidalia nije bila u mogućnosti otvoriti odabranu poveznicu u vašem Web pregledniku. Još uvijek možete kopirati URL i zalijepiti ga u vaš preglednik."
+
+msgctxt "HelpTextBrowser"
+msgid "Error opening help file:"
+msgstr "Greška pri otvaranju datoteke pomoći:"
+
+msgctxt "LicenseDialog"
+msgid "License Information"
+msgstr "Informacije o Licenci"
+
+msgctxt "LicenseDialog"
+msgid "License"
+msgstr "Licenca"
+
+msgctxt "LicenseDialog"
+msgid "Credits"
+msgstr "Zasluge"
+
+msgctxt "LogEvent"
+msgid "Debug"
+msgstr "Debugiranje"
+
+msgctxt "LogEvent"
+msgid "Info"
+msgstr "Info"
+
+msgctxt "LogEvent"
+msgid "Notice"
+msgstr "Obavijest"
+
+msgctxt "LogEvent"
+msgid "Warning"
+msgstr "Upozorenje"
+
+msgctxt "LogEvent"
+msgid "Error"
+msgstr "Greška"
+
+msgctxt "LogEvent"
+msgid "Unknown"
+msgstr "Nepoznato"
+
+msgctxt "LogTreeItem"
+msgid "Debug"
+msgstr "Debugiranje"
+
+msgctxt "LogTreeItem"
+msgid "Info"
+msgstr "Info"
+
+msgctxt "LogTreeItem"
+msgid "Notice"
+msgstr "Obavijest"
+
+msgctxt "LogTreeItem"
+msgid "Warning"
+msgstr "Upozorenje"
+
+msgctxt "LogTreeItem"
+msgid "Error"
+msgstr "Greška"
+
+msgctxt "LogTreeItem"
+msgid "Unknown"
+msgstr "Nepoznato"
+
+msgctxt "MainWindow"
+msgid "Start Tor"
+msgstr "Pokreni Tor"
+
+msgctxt "MainWindow"
+msgid "Exit"
+msgstr "Izlaz"
+
+msgctxt "MainWindow"
+msgid "Bandwidth Graph"
+msgstr "Graf Propusnosti"
+
+msgctxt "MainWindow"
+msgid "Message Log"
+msgstr "Dnevnik Poruka"
+
+msgctxt "MainWindow"
+msgid "Network Map"
+msgstr "Mrežna Karta"
+
+msgctxt "MainWindow"
+msgid "Control Panel"
+msgstr "Kontrolna Ploča"
+
+msgctxt "MainWindow"
+msgid "Settings"
+msgstr "Postavke"
+
+msgctxt "MainWindow"
+msgid "About"
+msgstr "O"
+
+msgctxt "MainWindow"
+msgid "Help"
+msgstr "Pomoć"
+
+msgctxt "MainWindow"
+msgid "New Identity"
+msgstr "Novi Identitet"
+
+msgctxt "MainWindow"
+msgid "Ctrl+T"
+msgstr "Ctrl+T"
+
+msgctxt "MainWindow"
+msgid "Ctrl+B"
+msgstr "Ctrl+B"
+
+msgctxt "MainWindow"
+msgid "Ctrl+L"
+msgstr "Ctrl+L"
+
+msgctxt "MainWindow"
+msgid "Ctrl+N"
+msgstr "Ctrl+N"
+
+msgctxt "MainWindow"
+msgid "Ctrl+?"
+msgstr "Ctrl+?"
+
+msgctxt "MainWindow"
+msgid "Ctrl+I"
+msgstr "Ctrl+I"
+
+msgctxt "MainWindow"
+msgid "Ctrl+P"
+msgstr "Ctrl+P"
+
+msgctxt "MainWindow"
+msgid "Tor"
+msgstr "Tor"
+
+msgctxt "MainWindow"
+msgid "View"
+msgstr "Pogled"
+
+msgctxt "MainWindow"
+msgid "Vidalia Help"
+msgstr "Vidalia Pomoć"
+
+msgctxt "MainWindow"
+msgid "Error starting web browser"
+msgstr "Greška pri pokretanju web pretraživača"
+
+msgctxt "MainWindow"
+msgid "Vidalia was unable to start the configured web browser"
+msgstr "Vidalia nije bila u mogućnosti pokrenuti podešeni web pretraživač"
+
+msgctxt "MainWindow"
+msgid "Error starting IM client"
+msgstr "Greška pri pokretanju IM klijenta"
+
+msgctxt "MainWindow"
+msgid "Vidalia was unable to start the configured IM client"
+msgstr "Vidalia nije bila u mogućnosti pokrenuti podešeni IM klijent"
+
+msgctxt "MainWindow"
+msgid "Error starting proxy server"
+msgstr "Greška pri pokretanju proxy poslužitelja"
+
+msgctxt "MainWindow"
+msgid "Vidalia was unable to start the configured proxy server"
+msgstr "Vidalia nije bila u mogućnosti pokrenuti podešeni proxy poslužitelj"
+
+msgctxt "MainWindow"
+msgid "Connecting to a relay directory"
+msgstr "Spajanje na mapu releja"
+
+msgctxt "MainWindow"
+msgid "Establishing an encrypted directory connection"
+msgstr "Uspostavljanje šifrirane veze prema mapi"
+
+msgctxt "MainWindow"
+msgid "Retrieving network status"
+msgstr "Dohvaćanje statusa mreže"
+
+msgctxt "MainWindow"
+msgid "Loading network status"
+msgstr "Učitavanje statusa mreže"
+
+msgctxt "MainWindow"
+msgid "Loading authority certificates"
+msgstr "Učitavanje certifikata autoriteta"
+
+msgctxt "MainWindow"
+msgid "Requesting relay information"
+msgstr "Zahtjevanje informacije o releju"
+
+msgctxt "MainWindow"
+msgid "Loading relay information"
+msgstr "Učitavanje informacija o releju"
+
+msgctxt "MainWindow"
+msgid "Connecting to the Tor network"
+msgstr "Spajanje na Tor mrežu"
+
+msgctxt "MainWindow"
+msgid "Establishing a Tor circuit"
+msgstr "Uspostavljanje Tor kruga"
+
+msgctxt "MainWindow"
+msgid "Connected to the Tor network!"
+msgstr "Spojen na Tor mrežu!"
+
+msgctxt "MainWindow"
+msgid "miscellaneous"
+msgstr "razno"
+
+msgctxt "MainWindow"
+msgid "identity mismatch"
+msgstr "nepodudaranje identiteta"
+
+msgctxt "MainWindow"
+msgid "done"
+msgstr "gotovo"
+
+msgctxt "MainWindow"
+msgid "connection refused"
+msgstr "veza odbijena"
+
+msgctxt "MainWindow"
+msgid "connection timeout"
+msgstr "vrijeme čekanja veze isteklo"
+
+msgctxt "MainWindow"
+msgid "read/write error"
+msgstr "greška čitanja/pisanja"
+
+msgctxt "MainWindow"
+msgid "no route to host"
+msgstr "nema rute do domaćina"
+
+msgctxt "MainWindow"
+msgid "insufficient resources"
+msgstr "nedostatni resursi"
+
+msgctxt "MainWindow"
+msgid "unknown"
+msgstr "nepoznato"
+
+msgctxt "MainWindow"
+msgid "Tor is not running"
+msgstr "Tor nije pokrenut"
+
+msgctxt "MainWindow"
+msgid "Tor is shutting down"
+msgstr "Tor je u procesu gašenja"
+
+msgctxt "MainWindow"
+msgid "Stop Tor Now"
+msgstr "Zaustavi Tor Odmah"
+
+msgctxt "MainWindow"
+msgid "Stop Tor"
+msgstr "Zaustavi Tor"
+
+msgctxt "MainWindow"
+msgid "Starting the Tor software"
+msgstr "Pokrećem Tor software"
+
+msgctxt "MainWindow"
+msgid "Starting Tor"
+msgstr "Pokrećem Tor"
+
+msgctxt "MainWindow"
+msgid "Error Starting Tor"
+msgstr "Greška pri Pokretanju Tora"
+
+msgctxt "MainWindow"
+msgid ""
+"Vidalia was unable to start Tor. Check your settings to ensure the correct "
+"name and location of your Tor executable is specified."
+msgstr "Vidalia nije bila u mogućnosti pokrenuti Tor. Provjerite svoje postavke i uvjerite se da su naziv i lokacija vaše Tor izvršne datoteke ispravni."
+
+msgctxt "MainWindow"
+msgid "Connecting to Tor"
+msgstr "Spajanje na Tor"
+
+msgctxt "MainWindow"
+msgid "Connection Error"
+msgstr "Greška pri Spajanju"
+
+msgctxt "MainWindow"
+msgid "Relaying is Enabled"
+msgstr "Relej je Omogućen"
+
+msgctxt "MainWindow"
+msgid "Error Shutting Down"
+msgstr "Greška pri Isključivanju"
+
+msgctxt "MainWindow"
+msgid "Vidalia was unable to stop the Tor software."
+msgstr "Vidalia nije bila u mogućnosti zaustaviti Tor software."
+
+msgctxt "MainWindow"
+msgid "Unexpected Error"
+msgstr "Neočekivana Greška"
+
+msgctxt "MainWindow"
+msgid "Authenticating to Tor"
+msgstr "Autentificiranje Toru"
+
+msgctxt "MainWindow"
+msgid "Cookie Authentication Required"
+msgstr "Zahtjevana Autentifikacija Cookijima"
+
+msgctxt "MainWindow"
+msgid ""
+"The Tor software requires Vidalia to send the contents of an authentication "
+"cookie, but Vidalia was unable to find one."
+msgstr "Tor software traži od Vidalije da pošalje sadržaj autentifikacijskog cookia, ali Vidalia ga nije bila u mogućnosti pronaći."
+
+msgctxt "MainWindow"
+msgid "Would you like to browse for the file 'control_auth_cookie' yourself?"
+msgstr "Dali biste sami željeli potražiti datoteku 'control_auth_cookie'?"
+
+msgctxt "MainWindow"
+msgid "Data Directory"
+msgstr "Podatkovna Mapa"
+
+msgctxt "MainWindow"
+msgid "Control Cookie (control_auth_cookie)"
+msgstr "Kontrolni Cookie (control_auth_cookie)"
+
+msgctxt "MainWindow"
+msgid "Error Registering for Events"
+msgstr "Greška pri Registriranju za Događaje"
+
+msgctxt "MainWindow"
+msgid ""
+"Vidalia was unable to register for some events. Many of Vidalia's features "
+"may be unavailable."
+msgstr "Vidalia nije bila u mogućnosti registrirati se za neke događaje. Mnoge mogućnosti Vidalije mogle bi biti nedostupne."
+
+msgctxt "MainWindow"
+msgid "Authentication Error"
+msgstr "Greška pri Autentifikaciji"
+
+msgctxt "MainWindow"
+msgid "Vidalia was unable to authenticate to the Tor software. (%1)"
+msgstr "Vidalija nije bila u mogućnosti autentificirati se Toru. (%1)"
+
+msgctxt "MainWindow"
+msgid "Please check your control port authentication settings."
+msgstr "Molimo provjerite svoje postavke autentifikacije kontrolnog porta."
+
+msgctxt "MainWindow"
+msgid "Tor Update Available"
+msgstr "Dostupno Ažuriranje Tora"
+
+msgctxt "MainWindow"
+msgid ""
+"The currently installed version of Tor is out of date or no longer "
+"recommended. Please visit the Tor website to download the latest version."
+msgstr "Trenutno instalirana inačica tora nije ažurna ili se više ne preporuča. Molimo posjetite Tor web stranicu za preuzimanje posljednje inačice."
+
+msgctxt "MainWindow"
+msgid "Tor website: %1"
+msgstr "Tor web stranica: %1"
+
+msgctxt "MainWindow"
+msgid ""
+"All subsequent connections will appear to be different than your old "
+"connections."
+msgstr "Sve daljnje veze činiti će se drugačije od vaše stare veze."
+
+msgctxt "MainWindow"
+msgid "Failed to Create New Identity"
+msgstr "Neuspješno Kreiranje Novog Identiteta"
+
+msgctxt "MainWindow"
+msgid "Port Forwarding Failed"
+msgstr "Preusmjeravanje Portova Neuspjelo"
+
+msgctxt "MainWindow"
+msgid "Vidalia was unable to configure automatic port forwarding."
+msgstr "Vidalia nije bila u mogućnosti podesiti automatsko preusmjeravanje portova."
+
+msgctxt "MainWindow"
+msgid "Vidalia Control Panel"
+msgstr "Vidalia Kontrolna Ploča"
+
+msgctxt "MainWindow"
+msgid "Status"
+msgstr "Status"
+
+msgctxt "MainWindow"
+msgid "Vidalia Shortcuts"
+msgstr "Vidalia Kratice"
+
+msgctxt "MainWindow"
+msgid "Setup Relaying"
+msgstr "Postavljanje Releja"
+
+msgctxt "MainWindow"
+msgid "Set up a relay and help the network grow"
+msgstr "Postavite relej i pomognite rastu mreže"
+
+msgctxt "MainWindow"
+msgid "View the Network"
+msgstr "Pregled Mreže"
+
+msgctxt "MainWindow"
+msgid "View a map of the Tor network"
+msgstr "Pregled karte Tor mreže"
+
+msgctxt "MainWindow"
+msgid "Use a New Identity"
+msgstr "Korištenje Novog Identiteta"
+
+msgctxt "MainWindow"
+msgid "Make subsequent connections appear new"
+msgstr "Učini da se daljnje veze čine novima"
+
+msgctxt "MainWindow"
+msgid "View recent bandwidth usage"
+msgstr "Pregled nedavnog korištenja propusnosti"
+
+msgctxt "MainWindow"
+msgid "View log message history"
+msgstr "Pregled povijesti dnevnika poruka"
+
+msgctxt "MainWindow"
+msgid "View help documentation"
+msgstr "Pregled pomoćne dokumentacije"
+
+msgctxt "MainWindow"
+msgid "Configure Vidalia"
+msgstr "Podešavanje Vidalije"
+
+msgctxt "MainWindow"
+msgid "View version and license information"
+msgstr "Pregled informacija inačice i licence"
+
+msgctxt "MainWindow"
+msgid "Exit Vidalia"
+msgstr "Izlaz iz Vidalie"
+
+msgctxt "MainWindow"
+msgid "Show this window on startup"
+msgstr "Prikaži ovaj prozor pri pokretanju"
+
+msgctxt "MainWindow"
+msgid "Hide"
+msgstr "Sakrij"
+
+msgctxt "MainWindow"
+msgid "Hide this window"
+msgstr "Sakrij ovaj prozor"
+
+msgctxt "MainWindow"
+msgid "Password Reset Failed"
+msgstr "Resetiranje Lozinke Neuspjelo"
+
+msgctxt "MainWindow"
+msgid ""
+"Vidalia tried to reset Tor's control password, but was not able to restart "
+"the Tor software. Please check your Task Manager to ensure there are no "
+"other Tor processes running."
+msgstr "Vidalia je pokušala resetirati Tor kontrolnu lozinku, ali nije bila u mogućnosti ponovno pokrenuti Tor. Molimo provjerite svoj Task Manager da biste se uvjerili da nema trenutno drugih pokrenutih Tor procesa."
+
+msgctxt "MainWindow"
+msgid ""
+"The currently installed version of Tor is out of date or no longer "
+"recommended."
+msgstr "Trenutno instalirana inačica Tora je zastarjela i nije više preporučena."
+
+msgctxt "MainWindow"
+msgid ""
+"Would you like to check if a newer package is available for installation?"
+msgstr "Dali biste željeli provjeriti ako postoji novi paket dostupan za instalaciju?"
+
+msgctxt "MainWindow"
+msgid "Potentially Unsafe Connection"
+msgstr "Potencijalno Nesigurna Veza"
+
+msgctxt "MainWindow"
+msgid ""
+"Tor has automatically closed your connection in order to protect your "
+"anonymity."
+msgstr "Tor je automatski zatvorio vašu vezu kako bi zaštitio vašu anonimnost."
+
+msgctxt "MainWindow"
+msgid "Update Failed"
+msgstr "Ažuriranje Neuspjelo"
+
+msgctxt "MainWindow"
+msgid "Your software is up to date"
+msgstr "Vaš software je ažuran."
+
+msgctxt "MainWindow"
+msgid ""
+"There are no new Tor software packages available for your computer at this "
+"time."
+msgstr "Nema novih Tor paketa dostupnih za vaše računalo u ovom trenutku."
+
+msgctxt "MainWindow"
+msgid "Installation Failed"
+msgstr "Instalacija Neuspjela"
+
+msgctxt "MainWindow"
+msgid "Vidalia was unable to install your software updates."
+msgstr "Vidalia nije bila u mogućnosti instalirati ažuriranja softwarea."
+
+msgctxt "MainWindow"
+msgid "The following error occurred:"
+msgstr "Sljedeća greška se pojavila:"
+
+msgctxt "MainWindow"
+msgid ""
+"Anything sent over this connection could be monitored. Please check your "
+"application's configuration and use only encrypted protocols, such as SSL, "
+"if possible."
+msgstr "Sve poslano preko ove veze može biti nadgledano. Molimo provjerite postavke svoje aplikacije i koristite samo šifrirane protokole, poput SSL-a, ukoliko je moguće."
+
+msgctxt "MainWindow"
+msgid "Bootstrapping torrc from %1 to %2"
+msgstr "Bootstrapping torrc iz %1 u %2"
+
+msgctxt "MainWindow"
+msgid "(probably Telnet)"
+msgstr "(vjerojatno Telnet)"
+
+msgctxt "MainWindow"
+msgid "(probably an email client)"
+msgstr "(vjerojatno email klijent)"
+
+msgctxt "MainWindow"
+msgid ""
+"One of your applications %1 appears to be making a potentially unencrypted "
+"and unsafe connection to port %2."
+msgstr "Jedna od vaših aplikacija %1 čini se pokušava napraviti potencijalno nešifriranu i nesigurnu vezu na port %2."
+
+msgctxt "MainWindow"
+msgid "failed (%1)"
+msgstr "neuspjelo (%1)"
+
+msgctxt "MainWindow"
+msgid ""
+"Your relay is shutting down.\n"
+"Click 'Stop' again to stop your relay now."
+msgstr "Vaš relej je u procesu gašenja.\nKliknite 'Zaustavi' ponovno za trenutno zaustavljanje releja."
+
+msgctxt "MainWindow"
+msgid ""
+"Vidalia can't find out how to talk to Tor because it can't access this file: %1\n"
+"\n"
+"Here's the last error message:\n"
+"%2"
+msgstr "Vidalia ne može saznati kako komunicirati sa Tor-om zato jer ne može pristupiti ovoj datoteci: %1\n\nOvdje je posljednja poruka greške:\n%2"
+
+msgctxt "MainWindow"
+msgid ""
+"It seems Tor has stopped running since Vidalia started it.\n"
+"\n"
+"See the Advanced Message Log for more information."
+msgstr "Čini se da je Tor prestao sa radom od kada je Vidalia pokrenuta.\n\nPogledajte 'Napredni popis poruka' za više informacija."
+
+msgctxt "MainWindow"
+msgid ""
+"You are currently running a relay. Terminating your relay will interrupt any open connections from clients.\n"
+"\n"
+"Would you like to shutdown gracefully and give clients time to find a new relay?"
+msgstr "Trenutno imate pokrenut relej. Gašenjem svog releja ćete prekinuti sve trenutno otvorene veze klijenata.\n\nŽelite li pravilno ugasiti i dozvoliti klijentima vrijeme za pronalazak novog releja?"
+
+msgctxt "MainWindow"
+msgid ""
+"Vidalia detected that the Tor software exited unexpectedly.\n"
+"\n"
+"Please check the message log for recent warning or error messages."
+msgstr "Vidalia je detektirala da je Tor neočekivano izašao.\n\nMolimo provjerite dnevnik poruka za nedavna upozorenja i greške."
+
+msgctxt "MessageLog"
+msgid "Error Setting Filter"
+msgstr "Filter Postavki Grešaka"
+
+msgctxt "MessageLog"
+msgid "Vidalia was unable to register for Tor's log events."
+msgstr "Vidalia se nije uspjela prijaviti za dnevnik događaja Tora."
+
+msgctxt "MessageLog"
+msgid "Error Opening Log File"
+msgstr "Greška pri Otvaranju Datoteke Dnevnika"
+
+msgctxt "MessageLog"
+msgid "Vidalia was unable to open the specified log file."
+msgstr "Vidalia nije bila u mogućnosti otvoriti specificiranu datoteku dnevnika."
+
+msgctxt "MessageLog"
+msgid "Log Filename Required"
+msgstr "Naziv Datoteke Dnevnika Potreban"
+
+msgctxt "MessageLog"
+msgid "You must enter a filename to be able to save log messages to a file."
+msgstr "Morate unesti naziv datoteke da biste bili u mogućnosti spremati poruke dnevnika u datoteku."
+
+msgctxt "MessageLog"
+msgid "Select Log File"
+msgstr "Odaberi Datoteku Dnevnika"
+
+msgctxt "MessageLog"
+msgid "Save Log Messages"
+msgstr "Spremi Poruke Dnevnika"
+
+msgctxt "MessageLog"
+msgid "Text Files (*.txt)"
+msgstr "Tekstualne Datoteke (*.txt)"
+
+msgctxt "MessageLog"
+msgid "Vidalia"
+msgstr "Vidalia"
+
+msgctxt "MessageLog"
+msgid "Find in Message Log"
+msgstr "Pronađi u Dnevniku Poruka"
+
+msgctxt "MessageLog"
+msgid "Find:"
+msgstr "Pronađi:"
+
+msgctxt "MessageLog"
+msgid "Not Found"
+msgstr "Nije Pronađeno"
+
+msgctxt "MessageLog"
+msgid "Search found 0 matches."
+msgstr "Pretraga je pronašla 0 podudarnosti."
+
+msgctxt "MessageLog"
+msgid "Message Log"
+msgstr "Dnevnik Poruka"
+
+msgctxt "MessageLog"
+msgid "Message Filters..."
+msgstr "Filteri Poruka..."
+
+msgctxt "MessageLog"
+msgid "Set message filters"
+msgstr "Postavi filtere poruka"
+
+msgctxt "MessageLog"
+msgid "History Size..."
+msgstr "Veličina Povijesti..."
+
+msgctxt "MessageLog"
+msgid "Set maximum number of messages to display"
+msgstr "Postavi maksimalni broj poruka za prikaz"
+
+msgctxt "MessageLog"
+msgid "Clear"
+msgstr "Očisti"
+
+msgctxt "MessageLog"
+msgid "Clear all messages from the Message Log (Ctrl+E)"
+msgstr "Očisti sve poruke iz Dnevnika Poruka (Ctrl+E)"
+
+msgctxt "MessageLog"
+msgid "Ctrl+E"
+msgstr "Ctrl+E"
+
+msgctxt "MessageLog"
+msgid "Copy"
+msgstr "Kopiraj"
+
+msgctxt "MessageLog"
+msgid "Copy the selected messages to the clipboard (Ctrl+C)"
+msgstr "Kopiraj odabrane poruke u međuspremnik (Ctrl+C)"
+
+msgctxt "MessageLog"
+msgid "Ctrl+C"
+msgstr "Ctrl+C"
+
+msgctxt "MessageLog"
+msgid "Select All"
+msgstr "Odaberi Sve"
+
+msgctxt "MessageLog"
+msgid "Select all messages (Ctrl+A)"
+msgstr "Odaberi sve poruke (Ctrl+A)"
+
+msgctxt "MessageLog"
+msgid "Ctrl+A"
+msgstr "Ctrl+A"
+
+msgctxt "MessageLog"
+msgid "Save All"
+msgstr "Spremi Sve"
+
+msgctxt "MessageLog"
+msgid "Save all messages to a file"
+msgstr "Spremi sve poruke u datoteku"
+
+msgctxt "MessageLog"
+msgid "Save Selected"
+msgstr "Spremi odabrano"
+
+msgctxt "MessageLog"
+msgid "Save selected messages to a file"
+msgstr "Spremi odabrane poruke u datoteku"
+
+msgctxt "MessageLog"
+msgid "Settings"
+msgstr "Postavke"
+
+msgctxt "MessageLog"
+msgid "Adjust Message Log Settings"
+msgstr "Prilagodi Postavke Dnevnika Poruka"
+
+msgctxt "MessageLog"
+msgid "Ctrl+T"
+msgstr "Ctrl+T"
+
+msgctxt "MessageLog"
+msgid "Help"
+msgstr "Pomoć"
+
+msgctxt "MessageLog"
+msgid "Show the help browser"
+msgstr "Prikaži preglednih pomoći"
+
+msgctxt "MessageLog"
+msgid "F1"
+msgstr "F1"
+
+msgctxt "MessageLog"
+msgid "Close"
+msgstr "Zatvori"
+
+msgctxt "MessageLog"
+msgid "Close the Message Log"
+msgstr "Zatvori Dnevnik Poruka"
+
+msgctxt "MessageLog"
+msgid "Esc"
+msgstr "Esc"
+
+msgctxt "MessageLog"
+msgid "Find"
+msgstr "Pronađi"
+
+msgctxt "MessageLog"
+msgid "Find all messages containing the search text (Ctrl+F)"
+msgstr "Pronađi sve poruke koje sadržavaju tekst pretrage (Ctrl+F)"
+
+msgctxt "MessageLog"
+msgid "Ctrl+F"
+msgstr "Ctrl+F"
+
+msgctxt "MessageLog"
+msgid "Time"
+msgstr "Vrijeme"
+
+msgctxt "MessageLog"
+msgid "Type"
+msgstr "Tip"
+
+msgctxt "MessageLog"
+msgid "Message"
+msgstr "Poruka"
+
+msgctxt "MessageLog"
+msgid "Saves the current Message Log settings"
+msgstr "Sprema trenutne postavke Dnevnika Poruka"
+
+msgctxt "MessageLog"
+msgid "Save Settings"
+msgstr "Spremi Postavke"
+
+msgctxt "MessageLog"
+msgid "Cancels changes made to settings"
+msgstr "Otkaži izmjene učinjenje postavkama"
+
+msgctxt "MessageLog"
+msgid "Cancel"
+msgstr "Odustani"
+
+msgctxt "MessageLog"
+msgid "Message Filter"
+msgstr "Filter Poruka"
+
+msgctxt "MessageLog"
+msgid "Error"
+msgstr "Greška"
+
+msgctxt "MessageLog"
+msgid "Warning"
+msgstr "Upozorenje"
+
+msgctxt "MessageLog"
+msgid "Notice"
+msgstr "Napomena"
+
+msgctxt "MessageLog"
+msgid "Info"
+msgstr "Info"
+
+msgctxt "MessageLog"
+msgid "Debug"
+msgstr "Debugiranje"
+
+msgctxt "MessageLog"
+msgid "Message Log History"
+msgstr "Povijest Dnevnika Poruka"
+
+msgctxt "MessageLog"
+msgid "Number of messages to display in the message log window"
+msgstr "Broj poruka koje će se prikazivati u prozoru dnevnika poruka"
+
+msgctxt "MessageLog"
+msgid "messages"
+msgstr "poruke"
+
+msgctxt "MessageLog"
+msgid "Browse"
+msgstr "Pretraži"
+
+msgctxt "MessageLog"
+msgid "Enable automatically saving all new log messages to a file"
+msgstr "Omogući automatsko spremanje novih poruka dnevnika u datoteku"
+
+msgctxt "MessageLog"
+msgid "Automatically save new log messages to a file"
+msgstr "Automatski spremi nove poruke dnevnika u datoteku"
+
+msgctxt "MessageLog"
+msgid "Basic"
+msgstr "Osnovno"
+
+msgctxt "MessageLog"
+msgid "Tor Status"
+msgstr "Tor Status"
+
+msgctxt "MessageLog"
+msgid "Advanced"
+msgstr "Napredno"
+
+msgctxt "MessageLog"
+msgid "Always Save New Log Messages"
+msgstr "Uvijek Spremi Nove Poruke Dnevnika"
+
+msgctxt "MessageLog"
+msgid ""
+"Messages that appear when something has \n"
+"gone very wrong and Tor cannot proceed."
+msgstr "Poruke koje se pojavljuju kada je nešto\nzaista pošlo po krivu i Tor ne može nastaviti."
+
+msgctxt "MessageLog"
+msgid ""
+"Messages that only appear when \n"
+"something has gone wrong with Tor."
+msgstr "Poruke koje se pojavljuju samo kada\nje nešto pošlo po krivu sa Torom."
+
+msgctxt "MessageLog"
+msgid ""
+"Messages that appear infrequently \n"
+"during normal Tor operation and are \n"
+"not considered errors, but you may \n"
+"care about."
+msgstr "Poruke koje se pojavljuju rijetko\ntijekom uobičajenog rada Tora i nisu\nsmatrane greškama, ali su vam\nmožda bitne."
+
+msgctxt "MessageLog"
+msgid ""
+"Messages that appear frequently \n"
+"during normal Tor operation."
+msgstr "Poruke koje se pojavljuju često\ntijekom uobičajenog rada Tora."
+
+msgctxt "MessageLog"
+msgid ""
+"Hyper-verbose messages primarily of \n"
+"interest to Tor developers."
+msgstr "Vrlo detaljne poruke od primarnog\ninteresa Tor developerima."
+
+msgctxt "MessageLog"
+msgid ""
+"Cannot write file %1\n"
+"\n"
+"%2."
+msgstr "Nije moguće zapisati datoteku %1\n\n%2."
+
+msgctxt "NetViewer"
+msgid "Tor Network Map"
+msgstr "Tor Karta Mreže"
+
+msgctxt "NetViewer"
+msgid "Refresh"
+msgstr "Osvježi"
+
+msgctxt "NetViewer"
+msgid "Refresh the list of Tor relays and connections"
+msgstr "Osvježi listu Tor releja i veza"
+
+msgctxt "NetViewer"
+msgid "Ctrl+R"
+msgstr "Ctrl+R"
+
+msgctxt "NetViewer"
+msgid "Help"
+msgstr "Pomoć"
+
+msgctxt "NetViewer"
+msgid "Show the network map help"
+msgstr "Prikaži pomoć karte mreže"
+
+msgctxt "NetViewer"
+msgid "Show network map help"
+msgstr "Prikaži pomoć karte mreže"
+
+msgctxt "NetViewer"
+msgid "F1"
+msgstr "F1"
+
+msgctxt "NetViewer"
+msgid "Close"
+msgstr "Zatvori"
+
+msgctxt "NetViewer"
+msgid "Close the network map"
+msgstr "Zatvori kartu mreže"
+
+msgctxt "NetViewer"
+msgid "Esc"
+msgstr "Esc"
+
+msgctxt "NetViewer"
+msgid "Zoom In"
+msgstr "Uvećaj"
+
+msgctxt "NetViewer"
+msgid "Zoom in on the network map"
+msgstr "Uvećavanje karte mreže"
+
+msgctxt "NetViewer"
+msgid "+"
+msgstr "+"
+
+msgctxt "NetViewer"
+msgid "Zoom Out"
+msgstr "Umanjivanje"
+
+msgctxt "NetViewer"
+msgid "Zoom out on the network map"
+msgstr "Umanjivanje karte mreže"
+
+msgctxt "NetViewer"
+msgid "-"
+msgstr "-"
+
+msgctxt "NetViewer"
+msgid "Zoom To Fit"
+msgstr "Uvećaj Optimalno"
+
+msgctxt "NetViewer"
+msgid "Zooms to fit all currently displayed circuits"
+msgstr "Uvećava dok se ne prikazuju svi trenutno prikazani krugovi."
+
+msgctxt "NetViewer"
+msgid "Ctrl+Z"
+msgstr "Ctrl+Z"
+
+msgctxt "NetViewer"
+msgid "Relay Not Found"
+msgstr "Relej Nije Pronađen"
+
+msgctxt "NetViewer"
+msgid "No details on the selected relay are available."
+msgstr "Nikakvi detalji o odabranom releju nisu dostupni."
+
+msgctxt "NetViewer"
+msgid "Unknown"
+msgstr "Nepoznato"
+
+msgctxt "NetViewer"
+msgid "Full Screen"
+msgstr "Cijeli Zaslon"
+
+msgctxt "NetViewer"
+msgid "View the network map as a full screen window"
+msgstr "Pregled karte mreže preko cijelog zaslona"
+
+msgctxt "NetViewer"
+msgid "Ctrl+F"
+msgstr "Ctrl+F"
+
+msgctxt "NetworkPage"
+msgid "Copy (Ctrl+C)"
+msgstr "Kopiraj (Ctrl+C)"
+
+msgctxt "NetworkPage"
+msgid ""
+"You must specify both an IP address or hostname and a port number to "
+"configure Tor to use a proxy to access the Internet."
+msgstr "Morate specificirati i IP adresu ili naziv domaćina i broj porta da biste podesili Tor za korištenje proxya za pristup Internetu."
+
+msgctxt "NetworkPage"
+msgid ""
+"You must specify one or more ports to which your firewall allows you to "
+"connect."
+msgstr "Morate specificirati jedan ili više portova na koje vam vaš vatrozid dozvoljava spajanje."
+
+msgctxt "NetworkPage"
+msgid "'%1' is not a valid port number."
+msgstr "'%1' nije važeći broj porta."
+
+msgctxt "NetworkPage"
+msgid "Check if your local network requires a proxy to access the Internet"
+msgstr "Provjerite dali vaša lokalna mreža zahtjeva proxy za pristup Internetu"
+
+msgctxt "NetworkPage"
+msgid "I use a proxy to access the Internet"
+msgstr "Koristim proxy za pristup Internetu"
+
+msgctxt "NetworkPage"
+msgid "Proxy Settings"
+msgstr "Postavke Proxya"
+
+msgctxt "NetworkPage"
+msgid "Username:"
+msgstr "Korisničko ime:"
+
+msgctxt "NetworkPage"
+msgid "Password:"
+msgstr "Lozinka:"
+
+msgctxt "NetworkPage"
+msgid "Port:"
+msgstr "Port:"
+
+msgctxt "NetworkPage"
+msgid "Check to only connect to relays using ports allowed by your firewall"
+msgstr "Označite za spajanje na releje samo portovima koje vaš vatrozid dozvoljava"
+
+msgctxt "NetworkPage"
+msgid "My firewall only lets me connect to certain ports"
+msgstr "Moj vatrozid mi dopušta spajanje samo na određene portove"
+
+msgctxt "NetworkPage"
+msgid "Firewall Settings"
+msgstr "Postavke Vatrozida"
+
+msgctxt "NetworkPage"
+msgid "Allowed Ports:"
+msgstr "Dozvoljeni Portovi:"
+
+msgctxt "NetworkPage"
+msgid "80, 443"
+msgstr "80, 443"
+
+msgctxt "NetworkPage"
+msgid ""
+"Check to encrypt directory requests and, optionally, use bridge relays to "
+"access the Tor network"
+msgstr "Označite za šifriranje zahtjeva za imenikom i, opcionalno, korištenje mostovnih releja za pristup Tor mreži"
+
+msgctxt "NetworkPage"
+msgid "My ISP blocks connections to the Tor network"
+msgstr "Moj ISP blokira veze prema Tor mreži"
+
+msgctxt "NetworkPage"
+msgid "Bridge Settings"
+msgstr "Postavke Mosta"
+
+msgctxt "NetworkPage"
+msgid "Add a Bridge:"
+msgstr "Dodaj Most:"
+
+msgctxt "NetworkPage"
+msgid "Remove the selected bridges from the list"
+msgstr "Ukloni odabrane mostove sa liste"
+
+msgctxt "NetworkPage"
+msgid "Copy the selected bridges to the clipboard"
+msgstr "Kopiraj odabrane mostove u međuspremnik"
+
+msgctxt "NetworkPage"
+msgid "Find Bridges Now"
+msgstr "Pronađi Mostove Sada"
+
+msgctxt "NetworkPage"
+msgid "<a href=\"bridges.finding\">How else can I find bridges?</a>"
+msgstr "<a href=\"bridges.finding\">Kako još mogu pronaći mostove?</a>"
+
+msgctxt "NetworkPage"
+msgid "<a href=\"bridges.finding\">How can I find bridges?</a>"
+msgstr "<a href=\"bridges.finding\">Kako mogu pronaći mostove?</a>"
+
+msgctxt "NetworkPage"
+msgid ""
+"No new bridges are currently available. You can either wait a while and try "
+"again, or try another method of finding new bridges."
+msgstr "Trenutno nema dostupnih novih mostova. Možete ili pričekati neko vrijeme i pokušati ponovno, ili pokušati nekom drugom metodom pronalaska novih mostova."
+
+msgctxt "NetworkPage"
+msgid "Click Help to see other methods of finding new bridges."
+msgstr "Kliknite Pomoć za pregled drugih metoda pronalaska novih mostova."
+
+msgctxt "NetworkPage"
+msgid "Address:"
+msgstr "Adresa:"
+
+msgctxt "NetworkPage"
+msgid "Type:"
+msgstr "Tip:"
+
+msgctxt "NetworkPage"
+msgid "You must select the proxy type."
+msgstr "Morate odabrati tip proxya."
+
+msgctxt "NetworkPage"
+msgid "SOCKS 4"
+msgstr "SOCKS 4"
+
+msgctxt "NetworkPage"
+msgid "SOCKS 5"
+msgstr "SOCKS 5"
+
+msgctxt "NetworkPage"
+msgid "HTTP / HTTPS"
+msgstr "HTTP / HTTPS"
+
+msgctxt "NetworkPage"
+msgid "You must specify one or more bridges."
+msgstr "Morate odrediti jedan ili više mostova."
+
+msgctxt "Policy"
+msgid "accept"
+msgstr "prihvati"
+
+msgctxt "Policy"
+msgid "reject"
+msgstr "odbij"
+
+msgctxt "RouterDescriptor"
+msgid "Online"
+msgstr "Online"
+
+msgctxt "RouterDescriptor"
+msgid "Hibernating"
+msgstr "Hibernacija"
+
+msgctxt "RouterDescriptor"
+msgid "Offline"
+msgstr "Offline"
+
+msgctxt "RouterDescriptorView"
+msgid "Location:"
+msgstr "Lokacija:"
+
+msgctxt "RouterDescriptorView"
+msgid "IP Address:"
+msgstr "IP Adresa:"
+
+msgctxt "RouterDescriptorView"
+msgid "Platform:"
+msgstr "Platforma:"
+
+msgctxt "RouterDescriptorView"
+msgid "Bandwidth:"
+msgstr "Propusnost:"
+
+msgctxt "RouterDescriptorView"
+msgid "Uptime:"
+msgstr "Vrijeme rada:"
+
+msgctxt "RouterDescriptorView"
+msgid "Last Updated:"
+msgstr "Posljednje Ažuriranje:"
+
+msgctxt "RouterDescriptorView"
+msgid "Copy"
+msgstr "Kopiraj"
+
+msgctxt "RouterInfoDialog"
+msgid "Hibernating"
+msgstr "Hiberniranje"
+
+msgctxt "RouterInfoDialog"
+msgid "Online"
+msgstr "Online"
+
+msgctxt "RouterInfoDialog"
+msgid "Offline"
+msgstr "Offline"
+
+msgctxt "RouterInfoDialog"
+msgid "Unknown"
+msgstr "Nepoznato"
+
+msgctxt "RouterInfoDialog"
+msgid "Relay Details"
+msgstr "Detalji Releja"
+
+msgctxt "RouterInfoDialog"
+msgid "Summary"
+msgstr "Sažetak"
+
+msgctxt "RouterInfoDialog"
+msgid "Name:"
+msgstr "Naziv:"
+
+msgctxt "RouterInfoDialog"
+msgid "Status:"
+msgstr "Status:"
+
+msgctxt "RouterInfoDialog"
+msgid "Location:"
+msgstr "Lokacija:"
+
+msgctxt "RouterInfoDialog"
+msgid "IP Address:"
+msgstr "IP Adresa:"
+
+msgctxt "RouterInfoDialog"
+msgid "Platform:"
+msgstr "Platforma:"
+
+msgctxt "RouterInfoDialog"
+msgid "Bandwidth:"
+msgstr "Propusnost:"
+
+msgctxt "RouterInfoDialog"
+msgid "Uptime:"
+msgstr "Vrijeme rada:"
+
+msgctxt "RouterInfoDialog"
+msgid "Contact:"
+msgstr "Kontakt:"
+
+msgctxt "RouterInfoDialog"
+msgid "Last Updated:"
+msgstr "Posljednje ažuriranje:"
+
+msgctxt "RouterInfoDialog"
+msgid "Descriptor"
+msgstr "Opis"
+
+msgctxt "RouterListItem"
+msgid "Offline"
+msgstr "Offline"
+
+msgctxt "RouterListItem"
+msgid "Hibernating"
+msgstr "Hiberniranje"
+
+msgctxt "RouterListItem"
+msgid "%1 KB/s"
+msgstr "%1 KB/s"
+
+msgctxt "RouterListWidget"
+msgid "Relay"
+msgstr "Relej"
+
+msgctxt "RouterListWidget"
+msgid "Zoom to Relay"
+msgstr "Uvećaj do Releja"
+
+msgctxt "RouterListWidget"
+msgid "%1 relays online"
+msgstr "%1 Releja Online"
+
+msgctxt "RouterListWidget"
+msgid "Copy"
+msgstr "Kopiraj"
+
+msgctxt "RouterListWidget"
+msgid "Nickname"
+msgstr "Nadimak"
+
+msgctxt "RouterListWidget"
+msgid "Fingerprint"
+msgstr "Otisak"
+
+msgctxt "ServerPage"
+msgid "Bridge Support Unavailable"
+msgstr "Podrška Mosta Nedostupna"
+
+msgctxt "ServerPage"
+msgid ""
+"You have configured Tor to act as a bridge relay for censored users, but "
+"your version of Tor does not support bridges."
+msgstr "Podesili ste Tor da se ponaša kao mostni relej za cenzurirane korisnike, ali vaša inačica Tora ne podržava mostove."
+
+msgctxt "ServerPage"
+msgid ""
+"Please upgrade your Tor software or configure Tor to act as a normal Tor "
+"relay."
+msgstr "Molimo ažurirajte vaš Tor software ili podesite Tor da se ponaša kao uobičajeni Tor relej."
+
+msgctxt "ServerPage"
+msgid "Your bridge relay is not running."
+msgstr "Vaš mostni relej nije pokrenut."
+
+msgctxt "ServerPage"
+msgid "You must specify at least a relay nickname and port."
+msgstr "Morate specificirati barem nadimak i port releja."
+
+msgctxt "ServerPage"
+msgid "Run as a client only"
+msgstr "Pokreni samo kao klijent"
+
+msgctxt "ServerPage"
+msgid "Relay Port:"
+msgstr "Port Releja:"
+
+msgctxt "ServerPage"
+msgid "Enable to mirror the relay directory"
+msgstr "Omogući za zrcaljenje imenika releja"
+
+msgctxt "ServerPage"
+msgid "Attempt to automatically configure port forwarding"
+msgstr "Pokušaj automatski podesiti preusmjeravanje portova"
+
+msgctxt "ServerPage"
+msgid "Test"
+msgstr "Test"
+
+msgctxt "ServerPage"
+msgid "Show help topic on port forwarding"
+msgstr "Prikaži temu pomoći vezanu uz preusmjeravanje portova"
+
+msgctxt "ServerPage"
+msgid "Directory Port:"
+msgstr "Port Imenika:"
+
+msgctxt "ServerPage"
+msgid "Directory Port Number"
+msgstr "Broj Porta Imenika"
+
+msgctxt "ServerPage"
+msgid "Contact Info:"
+msgstr "Kontakt Podaci:"
+
+msgctxt "ServerPage"
+msgid "Name of your relay"
+msgstr "Ime vašeg releja"
+
+msgctxt "ServerPage"
+msgid "Port on which users and other relays can communicate with your relay"
+msgstr "Port na kojem korisnici i drugi releji mogu komunicirati sa vašim relejom"
+
+msgctxt "ServerPage"
+msgid "Nickname:"
+msgstr "Nadimak:"
+
+msgctxt "ServerPage"
+msgid "Basic Settings"
+msgstr "Osnovne Postavke"
+
+msgctxt "ServerPage"
+msgid ""
+"For Internet connections with fast download speed but slow upload, please "
+"list your upload speed here."
+msgstr "Za Internet veze sa brzom brzinom preuzimanja i sporim slanjem, molimo navedite svoju brzinu slanja."
+
+msgctxt "ServerPage"
+msgid "Cable/DSL 256 Kbps"
+msgstr "Cable/DSL 256 Kbps"
+
+msgctxt "ServerPage"
+msgid "Cable/DSL 512 Kbps"
+msgstr "Cable/DSL 512 Kbps"
+
+msgctxt "ServerPage"
+msgid "Cable/DSL 768 Kbps"
+msgstr "Cable/DSL 768 Kbps"
+
+msgctxt "ServerPage"
+msgid "T1/Cable/DSL 1.5 Mbps"
+msgstr "T1/Cable/DSL 1.5 Mbps"
+
+msgctxt "ServerPage"
+msgid "> 1.5 Mbps"
+msgstr "> 1.5 Mbps"
+
+msgctxt "ServerPage"
+msgid "Custom"
+msgstr "Prilagođeno"
+
+msgctxt "ServerPage"
+msgid "Select the entry that most closely resembles your Internet connection"
+msgstr "Odaberite unos koji najbliže opisuje vašu Internet vezu"
+
+msgctxt "ServerPage"
+msgid "Show help topic on bandwidth rate limits"
+msgstr "Prikaži temu pomoći vezanu uz ograničenja propusnosti"
+
+msgctxt "ServerPage"
+msgid "Average Rate"
+msgstr "Prosječna brzina"
+
+msgctxt "ServerPage"
+msgid "Long-term average bandwidth limit"
+msgstr "Dugotrajno prosječno ograničenje propusnosti"
+
+msgctxt "ServerPage"
+msgid "KB/s"
+msgstr "KB/s"
+
+msgctxt "ServerPage"
+msgid "Maximum Rate"
+msgstr "Maksimalna Brzina"
+
+msgctxt "ServerPage"
+msgid "Peak bandwidth rate limit"
+msgstr "Vršno ograničenje propusnosti"
+
+msgctxt "ServerPage"
+msgid ""
+"Your maximum bandwidth rate must be greater than or equal to your average "
+"bandwidth rate. Both values must be at least 20 KB/s."
+msgstr "Vaša maksimalna propusnost mora biti veća od ili jednaka vašoj prosječnoj propusnosti. Obje vrijednosti moraju biti barem 20 KB/s."
+
+msgctxt "ServerPage"
+msgid "Bandwidth Limits"
+msgstr "Ograničenja Propusnosti"
+
+msgctxt "ServerPage"
+msgid "Ports 6660 - 6669 and 6697"
+msgstr "Portovi 6660 - 6669 i 6697"
+
+msgctxt "ServerPage"
+msgid "Internet Relay Chat (IRC)"
+msgstr "Internet Relay Chat (IRC)"
+
+msgctxt "ServerPage"
+msgid "Ports 110, 143, 993 and 995"
+msgstr "Portovi 110, 143, 993 i 995"
+
+msgctxt "ServerPage"
+msgid "Retrieve Mail (POP, IMAP)"
+msgstr "Dohvati Poštu (POP, IMAP)"
+
+msgctxt "ServerPage"
+msgid "Ports unspecified by other checkboxes"
+msgstr "Portovi nespecificirani drugim checkboxovima"
+
+msgctxt "ServerPage"
+msgid "Misc Other Services"
+msgstr "Razne Druge Usluge"
+
+msgctxt "ServerPage"
+msgid "Ports 706, 1863, 5050, 5190, 5222, 5223, 8300 and 8888"
+msgstr "Portovi 706, 1863, 5050, 5190, 5222, 5223, 8300 i 8888"
+
+msgctxt "ServerPage"
+msgid "Instant Messaging (IM)"
+msgstr "Instant Messaging (IM)"
+
+msgctxt "ServerPage"
+msgid "Port 443"
+msgstr "Port 443"
+
+msgctxt "ServerPage"
+msgid "Secure Websites (SSL)"
+msgstr "Sigurne Web Stranice (SSL)"
+
+msgctxt "ServerPage"
+msgid "Port 80"
+msgstr "Port 80"
+
+msgctxt "ServerPage"
+msgid "Websites"
+msgstr "Web Stranice"
+
+msgctxt "ServerPage"
+msgid "Show help topic on exit policies"
+msgstr "Prikaži teme pomoći vezane uz izlazne politike"
+
+msgctxt "ServerPage"
+msgid ""
+"What Internet resources should users be able to access from your relay?"
+msgstr "Kojim Internet resursima bi korisnik trebao biti u mogućnosti pristupiti sa vašeg releja?"
+
+msgctxt "ServerPage"
+msgid ""
+"Tor will still block some outgoing mail and file sharing applications by "
+"default to reduce spam and other abuse."
+msgstr "Tor će svejedno blokirati neke aplikacije za slanje pošte i dijeljenja datoteka po defaultu kako bi se smanjio spam i druge zloupotrebe."
+
+msgctxt "ServerPage"
+msgid "Exit Policies"
+msgstr "Izlazne Politike"
+
+msgctxt "ServerPage"
+msgid "Let others access your bridge by giving them this line:"
+msgstr "Dozvolite drugima pristup vašem mostu davanjem sljedećeg reda:"
+
+msgctxt "ServerPage"
+msgid ""
+"This is the identity of your bridge relay that you can give to other people"
+msgstr "Ovo je identitet vašeg mostnog releja koji možete davati drugim ljudima"
+
+msgctxt "ServerPage"
+msgid "Copy your bridge relay's identity to the clipboard"
+msgstr "Kopirajte identitet svog mostnog releja u međuspremnik"
+
+msgctxt "ServerPage"
+msgid "No Recent Usage"
+msgstr "Nema Nedavnog Korištenja"
+
+msgctxt "ServerPage"
+msgid "No clients have used your relay recently."
+msgstr "Niti jedan klijent nije nedavno koristio vaš relej."
+
+msgctxt "ServerPage"
+msgid ""
+"Leave your relay running so clients have a better chance of finding and "
+"using it."
+msgstr "Ostavite svoj relej pokrenut kako bi klijenti imali bolju šansu da ga pronađu i koriste."
+
+msgctxt "ServerPage"
+msgid "Bridge History"
+msgstr "Povijest Mosta"
+
+msgctxt "ServerPage"
+msgid "Vidalia was unable to retrieve your bridge's usage history."
+msgstr "Vidalia nije bila u mogućnosti dohvatiti povijest korištenja vašeg mosta."
+
+msgctxt "ServerPage"
+msgid ""
+"Tor returned an improperly formatted response when Vidalia requested your "
+"bridge's usage history."
+msgstr "Tor je vratio nepravilno formatirani odgovor kada je Vidalia zatražila povijest korištenja vašeg mosta."
+
+msgctxt "ServerPage"
+msgid "The returned response was: %1"
+msgstr "Vraćeni odgovor je bio: %1"
+
+msgctxt "ServerPage"
+msgid "Help censored users reach the Tor network"
+msgstr "Pomognite cenzuriranim korisnicima dolazak do Tor mreže"
+
+msgctxt "ServerPage"
+msgid "<a href=\"#bridgeUsage\">Who has used my bridge?</a>"
+msgstr "<a href=\"#bridgeUsage\">Tko je koristio moj most?</a>"
+
+msgctxt "ServerPage"
+msgid "<a href=\"#bridgeHelp\">What's this?</a>"
+msgstr "<a href=\"#bridgeHelp\">Što je ovo?</a>"
+
+msgctxt "ServerPage"
+msgid "Automatically distribute my bridge address"
+msgstr "Automatski distribuiraj adresu mog mosta"
+
+msgctxt "ServerPage"
+msgid "Relay traffic for the Tor network (exit relay)"
+msgstr "Relej prometa za Tor mrežu (napusti relej)"
+
+msgctxt "ServerPage"
+msgid "Relay traffic inside the Tor network (non-exit relay)"
+msgstr "Relej prometa unutar Tor mreže (nemoguće napuštanje releja)"
+
+msgctxt "ServerPage"
+msgid "Mirror the Relay Directory"
+msgstr "Zrcali Imenik Releja"
+
+msgctxt "ServerPage"
+msgid ""
+"Email address at which you may be reached if there is a\n"
+"problem with your relay. You might also include your PGP or GPG fingerprint."
+msgstr "Email adresa kojom vas se može doseći ako postoji\nproblem sa vašim relejom. Možete ujedno i uključiti vaš PGP ili GPG otisak."
+
+msgctxt "ServicePage"
+msgid "Error while trying to unpublish all services"
+msgstr "Greška pri povlačenju svih usluga"
+
+msgctxt "ServicePage"
+msgid ""
+"Please configure at least a service directory and a virtual port for each "
+"service you want to save. Remove the other ones."
+msgstr "Molimo podesite barem imenik usluga i virtualni port za svaku uslugu koju želite spremiti. Ukolnite ostale."
+
+msgctxt "ServicePage"
+msgid "Error"
+msgstr "Greška"
+
+msgctxt "ServicePage"
+msgid "Please select a Service."
+msgstr "Molimo odaberite Uslugu."
+
+msgctxt "ServicePage"
+msgid "Select Service Directory"
+msgstr "Odaberite Imenik Usluga"
+
+msgctxt "ServicePage"
+msgid "Virtual Port may only contain valid port numbers [1..65535]."
+msgstr "Virtualni Port može sadržavati samo važeće brojeve portova [1..65535]."
+
+msgctxt "ServicePage"
+msgid "Target may only contain address:port, address, or port."
+msgstr "Meta može sadržavati samo adresa:port, adresu, ili port."
+
+msgctxt "ServicePage"
+msgid "Directory already in use by another service."
+msgstr "Imenik već koristi neka druga usluga."
+
+msgctxt "ServicePage"
+msgid "Form"
+msgstr "Formular"
+
+msgctxt "ServicePage"
+msgid "Provided Hidden Services"
+msgstr "Pružene Skrivene Usluge"
+
+msgctxt "ServicePage"
+msgid "Onion Address"
+msgstr "Onion Adresa"
+
+msgctxt "ServicePage"
+msgid "Virtual Port"
+msgstr "Virtualni Port"
+
+msgctxt "ServicePage"
+msgid "Target"
+msgstr "Meta"
+
+msgctxt "ServicePage"
+msgid "Directory Path"
+msgstr "Putanja Imenika"
+
+msgctxt "ServicePage"
+msgid "Enabled"
+msgstr "Omogućeno"
+
+msgctxt "ServicePage"
+msgid "Add new service to list"
+msgstr "Dodaj novu uslugu na popis"
+
+msgctxt "ServicePage"
+msgid "Remove selected service from list"
+msgstr "Ukloni odabranu uslugu sa popisa"
+
+msgctxt "ServicePage"
+msgid "Copy onion address of selected service to clipboard"
+msgstr "Kopiraj onion adresu odabranog servisa u međuspremnik"
+
+msgctxt "ServicePage"
+msgid "Browse in local file system and choose directory for selected service"
+msgstr "Pretražite u lokalnom datotečnom sustavu i odaberite imenik za odabranu uslugu"
+
+msgctxt "ServicePage"
+msgid "Created by Tor"
+msgstr "Stvorio Tor"
+
+msgctxt "StatusEventWidget"
+msgid "Copy to Clipboard"
+msgstr "Kopiraj u Međuspremnik"
+
+msgctxt "StatusEventWidget"
+msgid "The Tor Software is Running"
+msgstr "Tor Software je Pokrenut"
+
+msgctxt "StatusEventWidget"
+msgid "You are currently running version \"%1\" of the Tor software."
+msgstr "Trenutno imate pokrenutu verziju \"%1\" Tor softwarea."
+
+msgctxt "StatusEventWidget"
+msgid "The Tor Software is not Running"
+msgstr "Tor Software nije Pokrenut"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Click \"Start Tor\" in the Vidalia Control Panel to restart the Tor "
+"software. If Tor exited unexpectedly, select the \"Advanced\" tab above for "
+"details about any errors encountered."
+msgstr "Kliknite \"Pokreni Tor\" u Vidalia Kontrolnoj Ploči za ponovno pokretanje Tor softwarea. Ako je Tor neočekivano izašao, odaberite tab \"Napredno\" za detalje o svim greškama na koje se naišlo."
+
+msgctxt "StatusEventWidget"
+msgid ""
+"You are currently running version \"%1\" of the Tor software, which is no "
+"longer recommended. Please upgrade to the most recent version of the "
+"software, which may contain important security, reliability and performance "
+"fixes."
+msgstr "Trenutno koristite inačicu \"%1\" Tor softwarea, koja se više ne preporuča. Molimo nadogradite na najnoviju inačicu softwarea, koja može sadržavate važne ispravke vezane uz pouzdanost, sigurnost i izvođenje."
+
+msgctxt "StatusEventWidget"
+msgid ""
+"You are currently running version \"%1\" of the Tor software, which may no "
+"longer work with the current Tor network. Please upgrade to the most recent "
+"version of the software, which may contain important security, reliability "
+"and performance fixes."
+msgstr "Trenutno koristite inačicu \"%1\" Tor softwarea, koja možda više ne radi sa trenutnom Tor mrežom. Molimo nadogradite na najnoviju inačicu softwarea, koja može sadržavate važne ispravke vezane uz pouzdanost, sigurnost i izvođenje."
+
+msgctxt "StatusEventWidget"
+msgid "Your Tor Software is Out-of-date"
+msgstr "Vaš Tor Software nije Ažuran"
+
+msgctxt "StatusEventWidget"
+msgid "Connected to the Tor Network"
+msgstr "Spojen na Tor Mrežu"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"We were able to successfully establish a connection to the Tor network. You "
+"can now configure your applications to use the Internet anonymously."
+msgstr "Bili smo u mogućnosti uspješno uspostaviti vezu na Tor mrežu. Sada možete podesiti vaše aplikacije za anonimno korištenje Interneta."
+
+msgctxt "StatusEventWidget"
+msgid "Tor Software Error"
+msgstr "Tor Greška"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"The Tor software encountered an internal bug. Please report the following "
+"error message to the Tor developers at bugs.torproject.org: \"%1\""
+msgstr "Tor software je naišao na unutarnju grešku. Molimo prijavite sljedeću grešku Tor developerima na bugs.torproject.org: \"%1\""
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Tor has determined that your computer's clock may be set to %1 seconds in "
+"the past compared to the source \"%2\". If your clock is not correct, Tor "
+"will not be able to function. Please verify your computer displays the "
+"correct time."
+msgstr "Tor je uočio da bi sat vašeg računala mogao biti podešen %1 sekundi u prošlost u usporedbi sa izvorom %2. Ako vaš sat nije ispravno podešen, Tor neće moći funkcionirati. Molimo provjerite dali vaše računalo prikazuje ispravno vrijeme."
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Tor has determined that your computer's clock may be set to %1 seconds in "
+"the future compared to the source \"%2\". If your clock is not correct, Tor "
+"will not be able to function. Please verify your computer displays the "
+"correct time."
+msgstr "Tor je uočio da bi sat vašeg računala mogao biti podešen %1 sekundi u budućnost u usporedbi sa izvorom %2. Ako vaš sat nije ispravno podešen, Tor neće moći funkcionirati. Molimo provjerite dali vaše računalo prikazuje ispravno vrijeme."
+
+msgctxt "StatusEventWidget"
+msgid "Your Computer's Clock is Potentially Incorrect"
+msgstr "Vrijeme Vašeg Računala je Moguće Neispravno"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"One of the applications on your computer may have attempted to make an "
+"unencrypted connection through Tor to port %1. Sending unencrypted "
+"information over the Tor network is dangerous and not recommended. For your "
+"protection, Tor has automatically closed this connection."
+msgstr "Moguće je da je jedna od aplikacija na vašem računalu pokušala uspostaviti nešifriranu vezu kroz Tor na port %1. Slanje nešifriranih informacija kroz Tor mrežu je opasno i nije preporučeno. Za vašu zaštitu, Tor je automatski zatvorio tu vezu."
+
+msgctxt "StatusEventWidget"
+msgid ""
+"One of the applications on your computer may have attempted to make an "
+"unencrypted connection through Tor to port %1. Sending unencrypted "
+"information over the Tor network is dangerous and not recommended."
+msgstr "Moguće je da je jedna od aplikacija na vašem računalu pokušala uspostaviti nešifriranu vezu kroz Tor na port %1. Slanje nešifriranih informacija kroz Tor mrežu je opasno i nije preporučeno."
+
+msgctxt "StatusEventWidget"
+msgid "Potentially Dangerous Connection!"
+msgstr "Potencijalno Opasna Veza!"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"One of your applications established a connection through Tor to \"%1\" "
+"using a protocol that may leak information about your destination. Please "
+"ensure you configure your applications to use only SOCKS4a or SOCKS5 with "
+"remote hostname resolution."
+msgstr "Jedna od aplikacija na vašem računalu uspostavila je vezu kroz Tor prema \"%1\" koristeći protokol koji može ispuštati informacije o vašem odredištu. Molimo uvjerite se da podešavate aplikacije za korištenje SOCKS4a ili SOCKS5 sa udaljenim razlučivanjem imena."
+
+msgctxt "StatusEventWidget"
+msgid "Unknown SOCKS Protocol"
+msgstr "Nepoznati SOCKS Protokol"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"One of your applications tried to establish a connection through Tor using a"
+" protocol that Tor does not understand. Please ensure you configure your "
+"applications to use only SOCKS4a or SOCKS5 with remote hostname resolution."
+msgstr "Jedna od vaših aplikacija pokušala je uspostaviti vezu kroz Tor koristeći protokol koji Tor ne razumije. Molimo uvjerite se da podešavate aplikacije za korištenje SOCKS4a ili SOCKS5 sa udaljenim razlučivanjem imena."
+
+msgctxt "StatusEventWidget"
+msgid "Invalid Destination Hostname"
+msgstr "Neispravni Naziv Odredišnog Poslužitelja"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"One of your applications tried to establish a connection through Tor to "
+"\"%1\", which Tor does not recognize as a valid hostname. Please check your "
+"application's configuration."
+msgstr "Jedna od vaših aplikacija pokušala je uspostaviti vezu kroz Tor prema \"%1\", što Tor ne raspoznaje kao ispravan naziv poslužitelja. Molimo provjerite postavke vaše aplikacije."
+
+msgctxt "StatusEventWidget"
+msgid "External IP Address Changed"
+msgstr "Vanjska IP Adresa Promjenjena"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Tor has determined your relay's public IP address is currently %1%2. If that"
+" is not correct, please consider setting the 'Address' option in your "
+"relay's configuration."
+msgstr "Tor je razlučio da je trenutna javna adresa vašeg releja %1%2. Ako to nije ispravno, molimo razmislite o postavljanju opcije 'Adresa' u konfiguraciji vašeg releja."
+
+msgctxt "StatusEventWidget"
+msgid "DNS Hijacking Detected"
+msgstr "Detektirano DNS Otimanje"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Tor detected that your DNS provider is providing false responses for domains"
+" that do not exist. Some ISPs and other DNS providers, such as OpenDNS, are "
+"known to do this in order to display their own search or advertising pages."
+msgstr "Tor je detektirao da vaš davatelj DNS usluga daje lažne odgovore za domene koje ne postoje. Neki ISP i drugi davatelji DNS usluga, poput OpenDNS-a, su poznati da to rade kako bi prikazivali svoje vlastite pretraživačke ili reklamne stranice."
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Tor detected that your DNS provider is providing false responses for well "
+"known domains. Since clients rely on Tor network relays to provide accurate "
+"DNS repsonses, your relay will not be configured as an exit relay."
+msgstr "Tor je detektirao da vaš davatelj DNS usluga daje lažne odgovore za dobro poznate domene. Pošto klijenti ovise o tome da releji daju ispravne DNS odgovore, vaš relej neće biti postavljen kao izlazni relej."
+
+msgctxt "StatusEventWidget"
+msgid "Checking Server Port Reachability"
+msgstr "Provjeravam Dostupnost Porta Poslužitelja"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Tor is trying to determine if your relay's server port is reachable from the"
+" Tor network by connecting to itself at %1:%2. This test could take several "
+"minutes."
+msgstr "Tor pokušava utvrditi dali je port poslužitelja vašeg releja dostupan kroz Tor mrežu tako da se spaja sam na sebe na %1:%2. Ovaj test bi mogao potrajati nekoliko minuta."
+
+msgctxt "StatusEventWidget"
+msgid "Server Port Reachability Test Successful!"
+msgstr "Test Dostupnosti Porta Poslužitelja Uspješan!"
+
+msgctxt "StatusEventWidget"
+msgid "Your relay's server port is reachable from the Tor network!"
+msgstr "Port poslužitelja vašeg releja je dostupan kroz Tor mrežu!"
+
+msgctxt "StatusEventWidget"
+msgid "Server Port Reachability Test Failed"
+msgstr "Test Dostupnosti Porta Poslužitelja Neuspješan"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Your relay's server port is not reachable by other Tor clients. This can "
+"happen if you are behind a router or firewall that requires you to set up "
+"port forwarding. If %1:%2 is not your correct IP address and server port, "
+"please check your relay's configuration."
+msgstr "Port poslužitelja vašeg releja nije dostupan drugim Tor klijentima. To se može dogoditi ukoliko ste iza rutera ili vatrozida koji zahtjeva podešavanje preusmjeravanja portova. Ako %1:%2 nije vaša ispravna IP adresa i port poslužitelja, molimo provjerite postavke svog releja."
+
+msgctxt "StatusEventWidget"
+msgid "Checking Directory Port Reachability"
+msgstr "Provjeravam Dostupnost Porta Imenika"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Tor is trying to determine if your relay's directory port is reachable from "
+"the Tor network by connecting to itself at %1:%2. This test could take "
+"several minutes."
+msgstr "Tor pokušava utvrditi ako je port imenika vašeg releja dostupan iz Tor mreže spajanjem na samoga sebe na %1:%2. Ovaj test bi mogao potrajati nekoliko minuta."
+
+msgctxt "StatusEventWidget"
+msgid "Directory Port Reachability Test Successful!"
+msgstr "Test Dostupnosti Porta Imenika Uspješan!"
+
+msgctxt "StatusEventWidget"
+msgid "Your relay's directory port is reachable from the Tor network!"
+msgstr "Port imenika vašeg releja je dostupan iz Tor mreže!"
+
+msgctxt "StatusEventWidget"
+msgid "Directory Port Reachability Test Failed"
+msgstr "Test Dostupnosti Porta Imenika Neuspješan"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Your relay's directory port is not reachable by other Tor clients. This can "
+"happen if you are behind a router or firewall that requires you to set up "
+"port forwarding. If %1:%2 is not your correct IP address and directory port,"
+" please check your relay's configuration."
+msgstr "Port imenika vašeg releja nije dostupan drugim Tor klijentima. To se može dogoditi ukoliko ste iza rutera ili vatrozida koji zahtjeva da postavite preusmjeravanje portova. Ako %1:%2 nije vaša ispravna IP adresa i port imenika, molimo provjerite postavke svog releja."
+
+msgctxt "StatusEventWidget"
+msgid "Relay Descriptor Rejected"
+msgstr "Opis Releja Odbijen"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Your relay's descriptor, which enables clients to connect to your relay, was"
+" rejected by the directory server at %1:%2. The reason given was: %3"
+msgstr "Opis vašeg releja, koji omogućava klijentima spajanje na vaš relej, je odbijen od strane poslužitelja imenika na %1:%2. Dani razlog je: %3"
+
+msgctxt "StatusEventWidget"
+msgid "Your Relay is Online"
+msgstr "Vaš Relej je Online"
+
+msgctxt "StatusEventWidget"
+msgid ""
+"Your relay is now online and available for Tor clients to use. You should "
+"see an increase in network traffic shown by the Bandwidth Graph within a few"
+" hours as more clients learn about your relay. Thank you for contributing to"
+" the Tor network!"
+msgstr "Vaš relej je sada online i dostupan za korištenje Tor klijentima. Trebali biste vidjeti povećanje mrežnog prometa prikazan Grafom Propusnosti kroz nekoliko sati kako više klijenata sazna za vaš relej. Hvala vam za doprinos Tor mreži!"
+
+msgctxt "Stream"
+msgid "New"
+msgstr "Novo"
+
+msgctxt "Stream"
+msgid "Resolving"
+msgstr "Razlučujem"
+
+msgctxt "Stream"
+msgid "Connecting"
+msgstr "Spajanje"
+
+msgctxt "Stream"
+msgid "Open"
+msgstr "Otvori"
+
+msgctxt "Stream"
+msgid "Failed"
+msgstr "Neuspješno"
+
+msgctxt "Stream"
+msgid "Closed"
+msgstr "Zatvoreno"
+
+msgctxt "Stream"
+msgid "Retrying"
+msgstr "Pokušavam ponovno"
+
+msgctxt "Stream"
+msgid "Remapped"
+msgstr "Premapiran"
+
+msgctxt "Stream"
+msgid "Unknown"
+msgstr "Nepoznato"
+
+msgctxt "TorProcess"
+msgid "Process %1 failed to stop. [%2]"
+msgstr "Proces %1 nije uspješno zaustavljen. [%2]"
+
+msgctxt "TorService"
+msgid "The Tor service is not installed."
+msgstr "Tor usloga nije instalirana."
+
+msgctxt "TorService"
+msgid "Unable to start the Tor service."
+msgstr "Nije bilo moguće pokrenuti Tor uslugu."
+
+msgctxt "TorSettings"
+msgid "Failed to hash the control password."
+msgstr "Neuspješno hashanje kontrolne lozinke."
+
+msgctxt "TorrcDialog"
+msgid "Editing torrc"
+msgstr "Izmjenjivanje torrc"
+
+msgctxt "TorrcDialog"
+msgid ""
+"Save settings. If unchecked it will only apply settings to the current Tor "
+"instance."
+msgstr "Spremi postavke. Ako nije odabrano, primjeniti će postavke samo na trentnu instancu Tora."
+
+msgctxt "TorrcDialog"
+msgid "Cut"
+msgstr "Izreži"
+
+msgctxt "TorrcDialog"
+msgid "Copy"
+msgstr "Kopiraj"
+
+msgctxt "TorrcDialog"
+msgid "Paste"
+msgstr "Zalijepi"
+
+msgctxt "TorrcDialog"
+msgid "Undo"
+msgstr "Poništi"
+
+msgctxt "TorrcDialog"
+msgid "Redo"
+msgstr "Ponovi"
+
+msgctxt "TorrcDialog"
+msgid "Select All"
+msgstr "Odaberi Sve"
+
+msgctxt "TorrcDialog"
+msgid "Apply all"
+msgstr "Primjeni Sve"
+
+msgctxt "TorrcDialog"
+msgid "Apply selection only"
+msgstr "Primjeni samo odabrano"
+
+msgctxt "TorrcDialog"
+msgid "Error connecting to Tor"
+msgstr "Greška pri spajanju na Tor"
+
+msgctxt "TorrcDialog"
+msgid "Selection is empty. Please select some text, or check \"Apply all\""
+msgstr "Selekcija je prazna. Molimo odaberite neki tekst, ili označite \"Primjeni sve\""
+
+msgctxt "TorrcDialog"
+msgid "Error at line %1: \"%2\""
+msgstr "Greška u liniji %1: \"%2\""
+
+msgctxt "TorrcDialog"
+msgid "Error"
+msgstr "Greška"
+
+msgctxt "TorrcDialog"
+msgid "An error ocurred while opening torrc file"
+msgstr "Greška se pojavila pri otvaranju torrc datoteke"
+
+msgctxt "UPNPControl"
+msgid "Success"
+msgstr "Uspjeh"
+
+msgctxt "UPNPControl"
+msgid "No UPnP-enabled devices found"
+msgstr "Nije pronađen niti jedan UPnP-omogućen uređaj"
+
+msgctxt "UPNPControl"
+msgid "No valid UPnP-enabled Internet gateway devices found"
+msgstr "Nije pronađen niti jedan UPnP-omogućen gateway uređaj"
+
+msgctxt "UPNPControl"
+msgid "WSAStartup failed"
+msgstr "WSAStartup neuspješan"
+
+msgctxt "UPNPControl"
+msgid "Failed to add a port mapping"
+msgstr "Neuspješno dodavanje port mape"
+
+msgctxt "UPNPControl"
+msgid "Failed to retrieve a port mapping"
+msgstr "Neuspješno dohvaćanje port mape"
+
+msgctxt "UPNPControl"
+msgid "Failed to remove a port mapping"
+msgstr "Neuspješno uklanjanje port mape"
+
+msgctxt "UPNPControl"
+msgid "Unknown error"
+msgstr "Nepoznata greška"
+
+msgctxt "UPNPTestDialog"
+msgid "Discovering UPnP-enabled devices"
+msgstr "Otkrivam UPnP-omogućene uređaje"
+
+msgctxt "UPNPTestDialog"
+msgid "Updating directory port mapping"
+msgstr "Ažuriram port mapu imenika"
+
+msgctxt "UPNPTestDialog"
+msgid "Updating relay port mapping"
+msgstr "Ažuriram port mapu releja"
+
+msgctxt "UPNPTestDialog"
+msgid "Test completed successfully!"
+msgstr "Test je uspješno završen!"
+
+msgctxt "UPNPTestDialog"
+msgid "Testing UPnP Support"
+msgstr "Testiranje UPnP Podrške"
+
+msgctxt "UPNPTestDialog"
+msgid "Testing Universal Plug & Play Support"
+msgstr "Testiram Universal Plug & Play Podršku"
+
+msgctxt "UpdateProcess"
+msgid ""
+"Vidalia was unable to check for available software updates because it could "
+"not find '%1'."
+msgstr "Vidalia nije bila u mogućnosti provjeriti za dostupna ažuriranja softwarea jer nije mogla pronaći '%1'."
+
+msgctxt "UpdateProcess"
+msgid ""
+"Vidalia was unable to check for available software updates because Tor's "
+"update process exited unexpectedly."
+msgstr "Vidalia nije bila u mogućnosti provjeriti za dostupna ažuriranja softwarea jer je Torov proces za ažuriranje neočekivano završio."
+
+msgctxt "UpdateProgressDialog"
+msgid "Checking for available updates..."
+msgstr "Provjeravam za dostupna ažuriranja..."
+
+msgctxt "UpdateProgressDialog"
+msgid "Hide"
+msgstr "Sakrij"
+
+msgctxt "UpdateProgressDialog"
+msgid "Downloading updates..."
+msgstr "Preuzimam ažuriranja..."
+
+msgctxt "UpdateProgressDialog"
+msgid "Installing updated software..."
+msgstr "Instaliram ažurirani software..."
+
+msgctxt "UpdateProgressDialog"
+msgid "Done! Your software is now up to date."
+msgstr "Gotovo! Vaš software je sada ažuran."
+
+msgctxt "UpdateProgressDialog"
+msgid "OK"
+msgstr "U redu"
+
+msgctxt "UpdateProgressDialog"
+msgid "Software Updates"
+msgstr "Ažuriranje Softwarea"
+
+msgctxt "UpdateProgressDialog"
+msgid "Checking for updates..."
+msgstr "Provjeravam za ažuriranja..."
+
+msgctxt "UpdateProgressDialog"
+msgid "Cancel"
+msgstr "Odustani"
+
+msgctxt "UpdatesAvailableDialog"
+msgid "Software Updates Available"
+msgstr "Ažuriranja Softwarea Dostupna"
+
+msgctxt "UpdatesAvailableDialog"
+msgid "Remind Me Later"
+msgstr "Podsjeti Me Kasnije"
+
+msgctxt "UpdatesAvailableDialog"
+msgid "Install"
+msgstr "Instaliraj"
+
+msgctxt "UpdatesAvailableDialog"
+msgid "The following updated software packages are ready for installation:"
+msgstr "Sljedeći ažurirani softwareski paketi su spremni za instalaciju:"
+
+msgctxt "UpdatesAvailableDialog"
+msgid "Package"
+msgstr "Paket"
+
+msgctxt "UpdatesAvailableDialog"
+msgid "Version"
+msgstr "Inačica"
+
+msgctxt "VMessageBox"
+msgid "OK"
+msgstr "U redu"
+
+msgctxt "VMessageBox"
+msgid "Cancel"
+msgstr "Odustani"
+
+msgctxt "VMessageBox"
+msgid "Yes"
+msgstr "Da"
+
+msgctxt "VMessageBox"
+msgid "No"
+msgstr "Ne"
+
+msgctxt "VMessageBox"
+msgid "Help"
+msgstr "Pomoć"
+
+msgctxt "VMessageBox"
+msgid "Retry"
+msgstr "Ponovni pokušaj"
+
+msgctxt "VMessageBox"
+msgid "Show Log"
+msgstr "Prikaži Dnevnik"
+
+msgctxt "VMessageBox"
+msgid "Show Settings"
+msgstr "Prikaži Postavke"
+
+msgctxt "VMessageBox"
+msgid "Continue"
+msgstr "Nastavi"
+
+msgctxt "VMessageBox"
+msgid "Quit"
+msgstr "Napusti"
+
+msgctxt "VMessageBox"
+msgid "Browse"
+msgstr "Pretraži"
+
+msgctxt "Vidalia"
+msgid "Invalid Argument"
+msgstr "Neispravan Argument"
+
+msgctxt "Vidalia"
+msgid "Vidalia is already running"
+msgstr "Vidalia je već pokrenuta"
+
+msgctxt "Vidalia"
+msgid "Displays this usage message and exits."
+msgstr "Prikazuje ovu poruku korištenja i izlazi."
+
+msgctxt "Vidalia"
+msgid "Resets ALL stored Vidalia settings."
+msgstr "Resetira SVE spremljene postavke Vidalie."
+
+msgctxt "Vidalia"
+msgid "Sets the directory Vidalia uses for data files."
+msgstr "Postavlja mapu koju Vidalia koristi za podatkovne datoteke."
+
+msgctxt "Vidalia"
+msgid "Sets the name and location of Vidalia's pidfile."
+msgstr "Postavlja naziv i lokaciju pid datoteke Vidalie."
+
+msgctxt "Vidalia"
+msgid "Sets the name and location of Vidalia's logfile."
+msgstr "Postavlja naziv i lokaciju datoteke dnevnika Vidalie."
+
+msgctxt "Vidalia"
+msgid "Sets the verbosity of Vidalia's logging."
+msgstr "Postavlja detaljnost imenika Vidalie."
+
+msgctxt "Vidalia"
+msgid "Sets Vidalia's interface style."
+msgstr "Postavlja stil sučelja Vidalie."
+
+msgctxt "Vidalia"
+msgid "Sets Vidalia's language."
+msgstr "Postavlja jezik Vidalie."
+
+msgctxt "Vidalia"
+msgid "Vidalia Usage Information"
+msgstr "Informacije Korištenja Vidalie"
+
+msgctxt "Vidalia"
+msgid "Unable to open log file '%1': %2"
+msgstr "Nije bilo moguće otvoriti datoteku dnevnika '%1': %2"
+
+msgctxt "Vidalia"
+msgid "Value required for parameter :"
+msgstr "Vrijednost potrebna za parametar :"
+
+msgctxt "Vidalia"
+msgid "Invalid language code specified:"
+msgstr "Specificiran neispravan kod jezika:"
+
+msgctxt "Vidalia"
+msgid "Invalid GUI style specified:"
+msgstr "Specificiran neispravan stil GUIa:"
+
+msgctxt "Vidalia"
+msgid "Invalid log level specified:"
+msgstr "Specificiran neispravan nivo zapisa dnevnika:"
+
+msgctxt "Vidalia"
+msgid ""
+"Another Vidalia process is possibly already running. If there really is not another Vidalia process running, you can choose to continue anyway.\n"
+"\n"
+"Would you like to continue starting Vidalia?"
+msgstr "Moguće je da je drugi proces Vidalie već pokrenut. Ako stvarno postoji drugi proces Vidalie koji je pokrenut, možete odabrati svejedno nastaviti.\n\nŽelite li nastaviti s pokretanjem Vidalie?"
+
+msgctxt "stringutil.h"
+msgid "%1 secs"
+msgstr "%1 sekundi"
+
+msgctxt "stringutil.h"
+msgid "%1 B/s"
+msgstr "%1 B/s"
+
+msgctxt "stringutil.h"
+msgid "%1 KB/s"
+msgstr "%1 KB/s"
+
+msgctxt "stringutil.h"
+msgid "%1 MB/s"
+msgstr "%1 MB/s"
+
+msgctxt "stringutil.h"
+msgid "%1 GB/s"
+msgstr "%1 GB/s"
+
+msgctxt "stringutil.h"
+msgid "%1 days"
+msgstr "%1 dana"
+
+msgctxt "stringutil.h"
+msgid "%1 hours"
+msgstr "%1 sati"
+
+msgctxt "stringutil.h"
+msgid "%1 mins"
+msgstr "%1 minuta"
diff --git a/ko_KR/qt_ko_KR.po b/ko_KR/qt_ko_KR.po
new file mode 100644
index 0000000..9ae0575
--- /dev/null
+++ b/ko_KR/qt_ko_KR.po
@@ -0,0 +1,434 @@
+# Translators:
+# Translators:
+# <SpicaRS(a)live.com>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: The Tor Project\n"
+"Report-Msgid-Bugs-To: https://trac.torproject.org/projects/tor\n"
+"POT-Creation-Date: 2008-08-20 03:25+0000\n"
+"PO-Revision-Date: 2012-02-14 09:47+0000\n"
+"Last-Translator: SpicaRS <SpicaRS(a)live.com>\n"
+"Language-Team: none\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ko_KR\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"X-Generator: Vidalia ts2po 0.2\n"
+
+#: qaccessibleobject.cpp:348
+msgctxt "QApplication"
+msgid "Activate"
+msgstr "가동"
+
+#: qmessagebox.h:319
+msgctxt "QApplication"
+msgid "Executable '%1' requires Qt %2, found Qt %3."
+msgstr "실행 파일 '%1'이 Qt %2를 요구했지만 %3이 발견되었어요."
+
+#: qmessagebox.h:321
+msgctxt "QApplication"
+msgid "Incompatible Qt Library Error"
+msgstr "Qt 라이브러리가 호환되지 않는 오류"
+
+#: qapplication.cpp:2095
+msgctxt "QApplication"
+msgid "QT_LAYOUT_DIRECTION"
+msgstr "QT_LAYOUT_DIRECTION"
+
+#: qaccessibleobject.cpp:350
+msgctxt "QApplication"
+msgid "Activates the program's main window"
+msgstr "프로그램의 메인 창을 띄우기"
+
+#: qmessagebox.cpp:2104
+msgctxt "QDialogButtonBox"
+msgid "OK"
+msgstr "확인"
+
+#: qdialogbuttonbox.cpp:528
+msgctxt "QDialogButtonBox"
+msgid "Save"
+msgstr "저장"
+
+#: qdialogbuttonbox.cpp:531
+msgctxt "QDialogButtonBox"
+msgid "Open"
+msgstr "열기"
+
+#: qdialogbuttonbox.cpp:534
+msgctxt "QDialogButtonBox"
+msgid "Cancel"
+msgstr "취소"
+
+#: qdialogbuttonbox.cpp:537
+msgctxt "QDialogButtonBox"
+msgid "Close"
+msgstr "닫기"
+
+#: qdialogbuttonbox.cpp:540
+msgctxt "QDialogButtonBox"
+msgid "Apply"
+msgstr "적용"
+
+#: qdialogbuttonbox.cpp:543
+msgctxt "QDialogButtonBox"
+msgid "Reset"
+msgstr "되돌리기"
+
+#: qdialogbuttonbox.cpp:546
+msgctxt "QDialogButtonBox"
+msgid "Help"
+msgstr "도움말"
+
+#: qdialogbuttonbox.cpp:550
+msgctxt "QDialogButtonBox"
+msgid "Don't Save"
+msgstr "저장 안 함"
+
+#: qdialogbuttonbox.cpp:554
+msgctxt "QDialogButtonBox"
+msgid "Discard"
+msgstr "버리기"
+
+#: qdialogbuttonbox.cpp:557
+msgctxt "QDialogButtonBox"
+msgid "&Yes"
+msgstr "예 (&Y)"
+
+#: qdialogbuttonbox.cpp:560
+msgctxt "QDialogButtonBox"
+msgid "Yes to &All"
+msgstr "모두 예 (&A)"
+
+#: qdialogbuttonbox.cpp:563
+msgctxt "QDialogButtonBox"
+msgid "&No"
+msgstr "아니오 (&N)"
+
+#: qdialogbuttonbox.cpp:566
+msgctxt "QDialogButtonBox"
+msgid "N&o to All"
+msgstr "모두 아니오 (&O)"
+
+#: qdialogbuttonbox.cpp:569
+msgctxt "QDialogButtonBox"
+msgid "Save All"
+msgstr "모두 저장"
+
+#: qdialogbuttonbox.cpp:572
+msgctxt "QDialogButtonBox"
+msgid "Abort"
+msgstr "건너뛰기"
+
+#: qdialogbuttonbox.cpp:575
+msgctxt "QDialogButtonBox"
+msgid "Retry"
+msgstr "다시 시도"
+
+#: qdialogbuttonbox.cpp:578
+msgctxt "QDialogButtonBox"
+msgid "Ignore"
+msgstr "무시"
+
+#: qdialogbuttonbox.cpp:581
+msgctxt "QDialogButtonBox"
+msgid "Restore Defaults"
+msgstr "기본값으로 돌림"
+
+#: qdialogbuttonbox.cpp:552
+msgctxt "QDialogButtonBox"
+msgid "Close without Saving"
+msgstr "저장 안 하고 끄기"
+
+#: qdialogbuttonbox.cpp:525
+msgctxt "QDialogButtonBox"
+msgid "&OK"
+msgstr "확인 (&O)"
+
+#: qdirmodel.cpp:423
+msgctxt "QDirModel"
+msgid "Name"
+msgstr "이름"
+
+#: qdirmodel.cpp:424
+msgctxt "QDirModel"
+msgid "Size"
+msgstr "크기"
+
+#: qdirmodel.cpp:427
+msgctxt "QDirModel"
+msgid "Kind"
+msgstr "종류"
+
+#: qdirmodel.cpp:429
+msgctxt "QDirModel"
+msgid "Type"
+msgstr "유형"
+
+#: qdirmodel.cpp:435
+msgctxt "QDirModel"
+msgid "Date Modified"
+msgstr "수정된 날짜"
+
+#: qfiledialog_win.cpp:126
+msgctxt "QFileDialog"
+msgid "All Files (*)"
+msgstr "모든 파일 (*)"
+
+#: qfiledialog.cpp:881
+msgctxt "QFileDialog"
+msgid "Directories"
+msgstr "경로"
+
+#: qfiledialog.cpp:2408
+msgctxt "QFileDialog"
+msgid "&Open"
+msgstr "열기 (&O)"
+
+#: qfiledialog.cpp:919
+msgctxt "QFileDialog"
+msgid "&Save"
+msgstr "저장 (&S)"
+
+#: qfiledialog.cpp:435
+msgctxt "QFileDialog"
+msgid "Open"
+msgstr "열기"
+
+#: qfiledialog.cpp:1670
+msgctxt "QFileDialog"
+msgid ""
+"%1 already exists.\n"
+"Do you want to replace it?"
+msgstr "%1은 이미 있습니다.\n덮어씌우시겠어요?"
+
+#: qfiledialog.cpp:1690
+msgctxt "QFileDialog"
+msgid ""
+"%1\n"
+"File not found.\n"
+"Please verify the correct file name was given."
+msgstr "%1\n파일을 찾지 못했어요.\n써주신 파일 이름이 정확한지 확인해주세요."
+
+#: qdirmodel.cpp:833
+msgctxt "QFileDialog"
+msgid "My Computer"
+msgstr "내 컴퓨터"
+
+#: qfiledialog.cpp:462
+msgctxt "QFileDialog"
+msgid "&Rename"
+msgstr "이름 바꾸기 (&R)"
+
+#: qfiledialog.cpp:463
+msgctxt "QFileDialog"
+msgid "&Delete"
+msgstr "지우기 (&D)"
+
+#: qfiledialog.cpp:464
+msgctxt "QFileDialog"
+msgid "Show &hidden files"
+msgstr "숨긴 파일 보이기 (%H)"
+
+#: ui_qfiledialog.h:264
+msgctxt "QFileDialog"
+msgid "Back"
+msgstr "뒤로"
+
+#: ui_qfiledialog.h:274
+msgctxt "QFileDialog"
+msgid "Parent Directory"
+msgstr "상위 경로"
+
+#: ui_qfiledialog.h:284
+msgctxt "QFileDialog"
+msgid "List View"
+msgstr "목록으로 보기"
+
+#: ui_qfiledialog.h:289
+msgctxt "QFileDialog"
+msgid "Detail View"
+msgstr "자세히 보기"
+
+#: ui_qfiledialog.h:292
+msgctxt "QFileDialog"
+msgid "Files of type:"
+msgstr "파일 유형:"
+
+#: qfiledialog.cpp:883
+msgctxt "QFileDialog"
+msgid "Directory:"
+msgstr "경로:"
+
+#: qfiledialog.cpp:2476
+msgctxt "QFileDialog"
+msgid ""
+"%1\n"
+"Directory not found.\n"
+"Please verify the correct directory name was given."
+msgstr "%1\n경로를 찾지 못했어요.\n써주신 경로 이름이 정확한지 확인해주세요."
+
+#: qfiledialog.cpp:2281
+msgctxt "QFileDialog"
+msgid ""
+"'%1' is write protected.\n"
+"Do you want to delete it anyway?"
+msgstr "'%1'은 쓰기 작업에 대해 보호되어 있어요.\n그래도 그냥 지우시겠어요?"
+
+#: qfiledialog.cpp:2286
+msgctxt "QFileDialog"
+msgid "Are sure you want to delete '%1'?"
+msgstr "정말 '%1'을 지우시겠어요?"
+
+#: qfiledialog.cpp:2299
+msgctxt "QFileDialog"
+msgid "Could not delete directory."
+msgstr "경로를 지울 수 없었어요."
+
+#: qfiledialog_win.cpp:128
+msgctxt "QFileDialog"
+msgid "All Files (*.*)"
+msgstr "모든 파일 (*.*)"
+
+#: qfiledialog.cpp:437
+msgctxt "QFileDialog"
+msgid "Save As"
+msgstr "다른 이름으로 저장"
+
+#: qfileiconprovider.cpp:379
+msgctxt "QFileDialog"
+msgid "Drive"
+msgstr "드라이브"
+
+#: qfileiconprovider.cpp:383
+msgctxt "QFileDialog"
+msgid "File"
+msgstr "파일"
+
+#: qfileiconprovider.cpp:412
+msgctxt "QFileDialog"
+msgid "Unknown"
+msgstr "알 수 없음"
+
+#: qfiledialog.cpp:439
+msgctxt "QFileDialog"
+msgid "Find Directory"
+msgstr "경로 찾기"
+
+#: qfiledialog.cpp:458
+msgctxt "QFileDialog"
+msgid "Show "
+msgstr "보이기 "
+
+#: ui_qfiledialog.h:269
+msgctxt "QFileDialog"
+msgid "Forward"
+msgstr "앞으로"
+
+#: qfiledialog.cpp:2137
+msgctxt "QFileDialog"
+msgid "New Folder"
+msgstr "새 폴더"
+
+#: qfiledialog.cpp:465
+msgctxt "QFileDialog"
+msgid "&New Folder"
+msgstr "새 폴더 (&N)"
+
+#: qfiledialog.cpp:917
+msgctxt "QFileDialog"
+msgid "&Choose"
+msgstr "고르기 (&C)"
+
+#: qsidebar.cpp:388
+msgctxt "QFileDialog"
+msgid "Remove"
+msgstr "삭제"
+
+#: qfiledialog.cpp:886
+msgctxt "QFileDialog"
+msgid "File &name:"
+msgstr "파일 이름 (&N):"
+
+#: ui_qfiledialog.h:261
+msgctxt "QFileDialog"
+msgid "Look in:"
+msgstr "찾을 위치:"
+
+#: ui_qfiledialog.h:279
+msgctxt "QFileDialog"
+msgid "Create New Folder"
+msgstr "새 폴더 만들기"
+
+#: qfilesystemmodel.cpp:761
+msgctxt "QFileSystemModel"
+msgid "Invalid filename"
+msgstr "잘못된 파일 이름"
+
+#: qfilesystemmodel.cpp:763
+msgctxt "QFileSystemModel"
+msgid ""
+"<b>The name \"%1\" can not be used.</b><p>Try using another name, with fewer"
+" characters or no punctuations marks."
+msgstr " <b> \"%1\"이란 이름은 쓸 수 없어요.</b><p>문장 부호를 지우거나 글자 수를 줄여서 이름을 바꾸어 보세요."
+
+#: qfilesystemmodel.cpp:832
+msgctxt "QFileSystemModel"
+msgid "Name"
+msgstr "이름"
+
+#: qfilesystemmodel.cpp:834
+msgctxt "QFileSystemModel"
+msgid "Size"
+msgstr "크기"
+
+#: qfilesystemmodel.cpp:838
+msgctxt "QFileSystemModel"
+msgid "Kind"
+msgstr "종류"
+
+#: qfilesystemmodel.cpp:840
+msgctxt "QFileSystemModel"
+msgid "Type"
+msgstr "유형"
+
+#: qfilesystemmodel.cpp:847
+msgctxt "QFileSystemModel"
+msgid "Date Modified"
+msgstr "수정한 날짜"
+
+#: qfilesystemmodel_p.h:198
+msgctxt "QFileSystemModel"
+msgid "My Computer"
+msgstr "내 컴퓨터"
+
+#: qfilesystemmodel_p.h:200
+msgctxt "QFileSystemModel"
+msgid "Computer"
+msgstr "컴퓨터"
+
+#: qfilesystemmodel.cpp:677
+msgctxt "QFileSystemModel"
+msgid "%1 TB"
+msgstr "%1 TB"
+
+#: qfilesystemmodel.cpp:679
+msgctxt "QFileSystemModel"
+msgid "%1 GB"
+msgstr "%1 GB"
+
+#: qfilesystemmodel.cpp:681
+msgctxt "QFileSystemModel"
+msgid "%1 MB"
+msgstr "%1 MB"
+
+#: qfilesystemmodel.cpp:683
+msgctxt "QFileSystemModel"
+msgid "%1 KB"
+msgstr "%1 KB"
+
+#: qfilesystemmodel.cpp:684
+msgctxt "QFileSystemModel"
+msgid "%1 bytes"
+msgstr "%1 바이트"
1
0
commit e2974e85a6560d204b674e7179a13074a3494536
Merge: bfb3973 7d96e78
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 13 17:12:27 2012 -0700
Merge extrainfo descriptor support
run_tests.py | 4 +
stem/descriptor/__init__.py | 158 ++++++-
stem/descriptor/extrainfo_descriptor.py | 684 +++++++++++++++++++++++
stem/descriptor/server_descriptor.py | 342 +++---------
test/integ/connection/authentication.py | 2 +-
test/integ/control/base_controller.py | 2 +-
test/integ/descriptor/__init__.py | 13 +-
test/integ/descriptor/data/extrainfo_descriptor | 12 +
test/integ/descriptor/extrainfo_descriptor.py | 102 ++++
test/integ/descriptor/reader.py | 6 +-
test/integ/descriptor/server_descriptor.py | 65 +--
test/integ/util/conf.py | 2 +-
test/runner.py | 15 +-
test/unit/descriptor/__init__.py | 2 +-
test/unit/descriptor/extrainfo_descriptor.py | 517 +++++++++++++++++
test/unit/descriptor/server_descriptor.py | 14 +-
16 files changed, 1621 insertions(+), 319 deletions(-)
1
0
commit 13944b062ff26a5efa178ff8d5552ff1d049574b
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 6 20:08:53 2012 -0700
Skeleton for extra-info descriptors
Basic module for parsing extrainfo descriptors. This doesn't actually do any
parsing yet, just turning the raw content into a ExtraInfoDescriptor instance.
This abstracts code we'll need out of the server_descriptor module so we'll be
able to use it.
What code there is here is exercised via the runner tests.
---
stem/descriptor/__init__.py | 158 ++++++++++++++++++++++-
stem/descriptor/extrainfo_descriptor.py | 111 ++++++++++++++++
stem/descriptor/server_descriptor.py | 159 +----------------------
test/integ/descriptor/data/extrainfo_descriptor | 12 ++
4 files changed, 286 insertions(+), 154 deletions(-)
diff --git a/stem/descriptor/__init__.py b/stem/descriptor/__init__.py
index 2af1fb0..f3a5983 100644
--- a/stem/descriptor/__init__.py
+++ b/stem/descriptor/__init__.py
@@ -8,9 +8,16 @@ Descriptor - Common parent for all descriptor file types.
+- __str__ - string that the descriptor was made from
"""
-__all__ = ["descriptor", "reader", "server_descriptor", "parse_file", "Descriptor"]
+__all__ = ["descriptor", "reader", "extrainfo_descriptor", "server_descriptor", "parse_file", "Descriptor"]
import os
+import re
+
+KEYWORD_CHAR = "a-zA-Z0-9-"
+WHITESPACE = " \t"
+KEYWORD_LINE = re.compile("^([%s]+)[%s]*(.*)$" % (KEYWORD_CHAR, WHITESPACE))
+PGP_BLOCK_START = re.compile("^-----BEGIN ([%s%s]+)-----$" % (KEYWORD_CHAR, WHITESPACE))
+PGP_BLOCK_END = "-----END %s-----"
def parse_file(path, descriptor_file):
"""
@@ -28,6 +35,7 @@ def parse_file(path, descriptor_file):
IOError if unable to read from the descriptor_file
"""
+ import stem.descriptor.extrainfo_descriptor
import stem.descriptor.server_descriptor
# The tor descriptor specifications do not provide a reliable method for
@@ -44,6 +52,10 @@ def parse_file(path, descriptor_file):
for desc in stem.descriptor.server_descriptor.parse_file(descriptor_file):
desc._set_path(path)
yield desc
+ elif filename == "cached-extrainfo" or first_line.startswith("extra-info "):
+ for desc in stem.descriptor.extrainfo_descriptor.parse_file(descriptor_file):
+ desc._set_path(path)
+ yield desc
else:
# unrecognized descriptor type
raise TypeError("Unable to determine the descriptor's type. filename: '%s', first line: '%s'" % (filename, first_line))
@@ -85,3 +97,147 @@ class Descriptor:
def __str__(self):
return self._raw_contents
+def _read_until_keyword(keyword, descriptor_file, inclusive = False):
+ """
+ Reads from the descriptor file until we get to the given keyword or reach the
+ end of the file.
+
+ Arguments:
+ keyword (str) - keyword we want to read until
+ descriptor_file (file) - file with the descriptor content
+ inclusive (bool) - includes the line with the keyword if True
+
+ Returns:
+ list with the lines until we find the keyword
+ """
+
+ content = []
+
+ while True:
+ last_position = descriptor_file.tell()
+ line = descriptor_file.readline()
+ if not line: break # EOF
+
+ if " " in line: line_keyword = line.split(" ", 1)[0]
+ else: line_keyword = line.strip()
+
+ if line_keyword == keyword:
+ if inclusive: content.append(line)
+ else: descriptor_file.seek(last_position)
+
+ break
+ else:
+ content.append(line)
+
+ return content
+
+def _get_pseudo_pgp_block(remaining_contents):
+ """
+ Checks if given contents begins with a pseudo-Open-PGP-style block and, if
+ so, pops it off and provides it back to the caller.
+
+ Arguments:
+ remaining_contents (list) - lines to be checked for a public key block
+
+ Returns:
+ str with the armor wrapped contents or None if it doesn't exist
+
+ Raises:
+ ValueError if the contents starts with a key block but it's malformed (for
+ instance, if it lacks an ending line)
+ """
+
+ if not remaining_contents:
+ return None # nothing left
+
+ block_match = PGP_BLOCK_START.match(remaining_contents[0])
+
+ if block_match:
+ block_type = block_match.groups()[0]
+ block_lines = []
+
+ while True:
+ if not remaining_contents:
+ raise ValueError("Unterminated pgp style block")
+
+ line = remaining_contents.pop(0)
+ block_lines.append(line)
+
+ if line == PGP_BLOCK_END % block_type:
+ return "\n".join(block_lines)
+ else:
+ return None
+
+def _get_descriptor_components(raw_contents, validate, extra_keywords):
+ """
+ Initial breakup of the server descriptor contents to make parsing easier.
+
+ A descriptor contains a series of 'keyword lines' which are simply a keyword
+ followed by an optional value. Lines can also be followed by a signature
+ block.
+
+ To get a sublisting with just certain keywords use extra_keywords. This can
+ be useful if we care about their relative ordering with respect to each
+ other. For instance, we care about the ordering of 'accept' and 'reject'
+ entries because this influences the resulting exit policy, but for everything
+ else in server descriptors the order does not matter.
+
+ Arguments:
+ raw_contents (str) - descriptor content provided by the relay
+ validate (bool) - checks the validity of the descriptor's content if
+ True, skips these checks otherwise
+ extra_keywords (list) - entity keywords to put into a separate listing with
+ ordering intact
+
+ Returns:
+ tuple with the following attributes...
+ entries (dict) - keyword => (value, pgp key) entries
+ first_keyword (str) - keyword of the first line
+ last_keyword (str) - keyword of the last line
+ extra_entries (list) - lines containing entries matching extra_keywords
+ """
+
+ entries = {}
+ first_keyword = None
+ last_keyword = None
+ extra_entries = [] # entries with a keyword in extra_keywords
+ remaining_lines = raw_contents.split("\n")
+
+ while remaining_lines:
+ line = remaining_lines.pop(0)
+
+ # last line can be empty
+ if not line and not remaining_lines: continue
+
+ # Some lines have an 'opt ' for backward compatability. They should be
+ # ignored. This prefix is being removed in...
+ # https://trac.torproject.org/projects/tor/ticket/5124
+
+ if line.startswith("opt "): line = line[4:]
+
+ line_match = KEYWORD_LINE.match(line)
+
+ if not line_match:
+ if not validate: continue
+ raise ValueError("Line contains invalid characters: %s" % line)
+
+ keyword, value = line_match.groups()
+
+ if not first_keyword: first_keyword = keyword
+ last_keyword = keyword
+
+ try:
+ block_contents = _get_pseudo_pgp_block(remaining_lines)
+ except ValueError, exc:
+ if not validate: continue
+ raise exc
+
+ if keyword in extra_keywords:
+ extra_entries.append("%s %s" % (keyword, value))
+ elif keyword in entries:
+ entries[keyword].append((value, block_contents))
+ else:
+ entries[keyword] = [(value, block_contents)]
+
+ return entries, first_keyword, last_keyword, extra_entries
+
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py
new file mode 100644
index 0000000..891ba18
--- /dev/null
+++ b/stem/descriptor/extrainfo_descriptor.py
@@ -0,0 +1,111 @@
+"""
+Parsing for Tor extra-info descriptors. These are published by relays whenever
+their server descriptor is published and have a similar format. However, unlike
+server descriptors these don't contain information that Tor clients require to
+function and as such aren't fetched by default.
+
+Defined in section 2.2 of the dir-spec, extra-info descriptors contain
+interesting but non-vital information such as usage statistics. These documents
+cannot be requested of bridges.
+
+Extra-info descriptors are available from a few sources...
+
+- if you have 'DownloadExtraInfo 1' in your torrc...
+ - control port via 'GETINFO extra-info/digest/*' queries
+ - the 'cached-extrainfo' file in tor's data directory
+- tor metrics, at https://metrics.torproject.org/data.html
+- directory authorities and mirrors via their DirPort
+
+parse_file - Iterates over the extra-info descriptors in a file.
+ExtraInfoDescriptor - Tor extra-info descriptor.
+"""
+
+import stem.descriptor
+
+def parse_file(descriptor_file, validate = True):
+ """
+ Iterates over the extra-info descriptors in a file.
+
+ Arguments:
+ descriptor_file (file) - file with descriptor content
+ validate (bool) - checks the validity of the descriptor's content if
+ True, skips these checks otherwise
+
+ Returns:
+ iterator for ExtraInfoDescriptor instances in the file
+
+ Raises:
+ ValueError if the contents is malformed and validate is True
+ IOError if the file can't be read
+ """
+
+ while True:
+ extrainfo_content = stem.descriptor._read_until_keyword("router-signature", descriptor_file)
+
+ # we've reached the 'router-signature', now include the pgp style block
+ block_end_prefix = stem.descriptor.PGP_BLOCK_END.split(' ', 1)[0]
+ extrainfo_content += stem.descriptor._read_until_keyword(block_end_prefix, descriptor_file, True)
+
+ if extrainfo_content:
+ yield ExtraInfoDescriptor("".join(extrainfo_content), validate)
+ else: break # done parsing file
+
+class ExtraInfoDescriptor(stem.descriptor.Descriptor):
+ """
+ Extra-info descriptor document.
+
+ Attributes:
+ nickname (str) - relay's nickname (*)
+ fingerprint (str) - fourty hex digits that make up the relay's fingerprint (*)
+ published (datetime.datetime) - time in GMT when the descriptor was generated (*)
+ geoip_db_digest (str) - sha1 of geoIP database file
+
+ read_history (str) - read-history line, always unset
+ read_history_end (datetime.datetime) - end of the sampling interval
+ read_history_interval (int) - seconds per interval
+ read_history_values (list) - bytes read during each interval (*)
+
+ write_history (str) - write-history line, always unset
+ write_history_end (datetime.datetime) - end of the sampling interval
+ write_history_interval (int) - seconds per interval
+ write_history_values (list) - bytes written during each interval (*)
+
+ (*) required fields, others are left as None if undefined
+ """
+
+ def __init__(self, raw_contents, validate = True, annotations = None):
+ """
+ Extra-info descriptor constructor, created from a relay's extra-info
+ content (as provided by "GETINFO extra-info/digest/*", cached contents, and
+ metrics).
+
+ By default this validates the descriptor's content as it's parsed. This
+ validation can be disables to either improve performance or be accepting of
+ malformed data.
+
+ Arguments:
+ raw_contents (str) - extra-info content provided by the relay
+ validate (bool) - checks the validity of the extra-info descriptor if
+ True, skips these checks otherwise
+
+ Raises:
+ ValueError if the contents is malformed and validate is True
+ """
+
+ stem.descriptor.Descriptor.__init__(self, raw_contents)
+
+ self.nickname = None
+ self.fingerprint = None
+ self.published = None
+ self.geoip_db_digest = None
+
+ self.read_history = None
+ self.read_history_end = None
+ self.read_history_interval = None
+ self.read_history_values = []
+
+ self.write_history = None
+ self.write_history_end = None
+ self.write_history_interval = None
+ self.write_history_values = []
+
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 551835d..b87ed2a 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -33,12 +33,6 @@ import stem.version
import stem.util.connection
import stem.util.tor_tools
-KEYWORD_CHAR = "a-zA-Z0-9-"
-WHITESPACE = " \t"
-KEYWORD_LINE = re.compile("^([%s]+)[%s]*(.*)$" % (KEYWORD_CHAR, WHITESPACE))
-PGP_BLOCK_START = re.compile("^-----BEGIN ([%s%s]+)-----$" % (KEYWORD_CHAR, WHITESPACE))
-PGP_BLOCK_END = "-----END %s-----"
-
# relay descriptors must have exactly one of the following
REQUIRED_FIELDS = (
"router",
@@ -127,56 +121,21 @@ def parse_file(descriptor_file, validate = True):
# to the caller).
while True:
- annotations = _read_until_keyword("router", descriptor_file)
- descriptor_content = _read_until_keyword("router-signature", descriptor_file)
+ annotations = stem.descriptor._read_until_keyword("router", descriptor_file)
+ descriptor_content = stem.descriptor._read_until_keyword("router-signature", descriptor_file)
# we've reached the 'router-signature', now include the pgp style block
- block_end_prefix = PGP_BLOCK_END.split(' ', 1)[0]
- descriptor_content += _read_until_keyword(block_end_prefix, descriptor_file, True)
+ block_end_prefix = stem.descriptor.PGP_BLOCK_END.split(' ', 1)[0]
+ descriptor_content += stem.descriptor._read_until_keyword(block_end_prefix, descriptor_file, True)
if descriptor_content:
# strip newlines from annotations
annotations = map(str.strip, annotations)
descriptor_text = "".join(descriptor_content)
- descriptor = RelayDescriptor(descriptor_text, validate, annotations)
- yield descriptor
+ yield RelayDescriptor(descriptor_text, validate, annotations)
else: break # done parsing descriptors
-def _read_until_keyword(keyword, descriptor_file, inclusive = False):
- """
- Reads from the descriptor file until we get to the given keyword or reach the
- end of the file.
-
- Arguments:
- keyword (str) - keyword we want to read until
- descriptor_file (file) - file with the descriptor content
- inclusive (bool) - includes the line with the keyword if True
-
- Returns:
- list with the lines until we find the keyword
- """
-
- content = []
-
- while True:
- last_position = descriptor_file.tell()
- line = descriptor_file.readline()
- if not line: break # EOF
-
- if " " in line: line_keyword = line.split(" ", 1)[0]
- else: line_keyword = line.strip()
-
- if line_keyword == keyword:
- if inclusive: content.append(line)
- else: descriptor_file.seek(last_position)
-
- break
- else:
- content.append(line)
-
- return content
-
class ServerDescriptor(stem.descriptor.Descriptor):
"""
Common parent for server descriptors.
@@ -297,7 +256,7 @@ class ServerDescriptor(stem.descriptor.Descriptor):
# does not matter so breaking it into key / value pairs.
entries, first_keyword, last_keyword, self.exit_policy = \
- _get_descriptor_components(raw_contents, validate)
+ stem.descriptor._get_descriptor_components(raw_contents, validate, ("accept", "reject"))
self._parse(entries, validate)
if validate: self._check_constraints(entries, first_keyword, last_keyword)
@@ -816,109 +775,3 @@ class BridgeDescriptor(ServerDescriptor):
def _first_keyword(self):
return "router"
-def _get_descriptor_components(raw_contents, validate):
- """
- Initial breakup of the server descriptor contents to make parsing easier.
-
- A descriptor contains a series of 'keyword lines' which are simply a keyword
- followed by an optional value. Lines can also be followed by a signature
- block.
-
- We care about the ordering of 'accept' and 'reject' entries because this
- influences the resulting exit policy, but for everything else the order does
- not matter so breaking it into key / value pairs.
-
- Arguments:
- raw_contents (str) - descriptor content provided by the relay
- validate (bool) - checks the validity of the descriptor's content if
- True, skips these checks otherwise
-
- Returns:
- tuple with the following attributes...
- entries (dict) - keyword => (value, pgp key) entries
- first_keyword (str) - keyword of the first line
- last_keyword (str) - keyword of the last line
- exit_policy (list) - lines containing the exit policy
- """
-
- entries = {}
- first_keyword = None
- last_keyword = None
- exit_policy = []
- remaining_lines = raw_contents.split("\n")
-
- while remaining_lines:
- line = remaining_lines.pop(0)
-
- # last line can be empty
- if not line and not remaining_lines: continue
-
- # Some lines have an 'opt ' for backward compatability. They should be
- # ignored. This prefix is being removed in...
- # https://trac.torproject.org/projects/tor/ticket/5124
-
- if line.startswith("opt "): line = line[4:]
-
- line_match = KEYWORD_LINE.match(line)
-
- if not line_match:
- if not validate: continue
- raise ValueError("Line contains invalid characters: %s" % line)
-
- keyword, value = line_match.groups()
-
- if not first_keyword: first_keyword = keyword
- last_keyword = keyword
-
- try:
- block_contents = _get_pseudo_pgp_block(remaining_lines)
- except ValueError, exc:
- if not validate: continue
- raise exc
-
- if keyword in ("accept", "reject"):
- exit_policy.append("%s %s" % (keyword, value))
- elif keyword in entries:
- entries[keyword].append((value, block_contents))
- else:
- entries[keyword] = [(value, block_contents)]
-
- return entries, first_keyword, last_keyword, exit_policy
-
-def _get_pseudo_pgp_block(remaining_contents):
- """
- Checks if given contents begins with a pseudo-Open-PGP-style block and, if
- so, pops it off and provides it back to the caller.
-
- Arguments:
- remaining_contents (list) - lines to be checked for a public key block
-
- Returns:
- str with the armor wrapped contents or None if it doesn't exist
-
- Raises:
- ValueError if the contents starts with a key block but it's malformed (for
- instance, if it lacks an ending line)
- """
-
- if not remaining_contents:
- return None # nothing left
-
- block_match = PGP_BLOCK_START.match(remaining_contents[0])
-
- if block_match:
- block_type = block_match.groups()[0]
- block_lines = []
-
- while True:
- if not remaining_contents:
- raise ValueError("Unterminated pgp style block")
-
- line = remaining_contents.pop(0)
- block_lines.append(line)
-
- if line == PGP_BLOCK_END % block_type:
- return "\n".join(block_lines)
- else:
- return None
-
diff --git a/test/integ/descriptor/data/extrainfo_descriptor b/test/integ/descriptor/data/extrainfo_descriptor
new file mode 100644
index 0000000..4525afe
--- /dev/null
+++ b/test/integ/descriptor/data/extrainfo_descriptor
@@ -0,0 +1,12 @@
+extra-info NINJA B2289C3EAB83ECD6EB916A2F481A02E6B76A0A48
+published 2012-05-05 17:03:50
+write-history 2012-05-05 17:02:45 (900 s) 1082368,19456,50176,272384,485376,1850368,1132544,1790976,2459648,4091904,6310912,13701120,3209216,3871744,7873536,5440512,7287808,10561536,9979904,11247616,11982848,7590912,10611712,20728832,38534144,6839296,3173376,16678912
+read-history 2012-05-05 17:02:45 (900 s) 3309568,9216,41984,27648,123904,2004992,364544,576512,1607680,3808256,4672512,12783616,2938880,2562048,7348224,3574784,6488064,10954752,9359360,4438016,6286336,6438912,4502528,10720256,38165504,1524736,2336768,8186880
+dirreq-write-history 2012-05-05 17:02:45 (900 s) 0,0,0,227328,349184,382976,738304,1171456,850944,657408,1675264,987136,702464,1335296,587776,1941504,893952,533504,695296,6828032,6326272,1287168,6310912,10085376,1048576,5372928,894976,8610816
+dirreq-read-history 2012-05-05 17:02:45 (900 s) 0,0,0,0,33792,27648,48128,46080,60416,51200,63488,64512,45056,27648,37888,48128,57344,34816,46080,50176,37888,51200,25600,33792,39936,32768,28672,30720
+router-signature
+-----BEGIN SIGNATURE-----
+K5FSywk7qvw/boA4DQcqkls6Ize5vcBYfhQ8JnOeRQC9+uDxbnpm3qaYN9jZ8myj
+k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw
+7LZqklu+gVvhMKREpchVqlAwXkWR44VENm24Hs+mT3M=
+-----END SIGNATURE-----
1
0

[stem/master] Basic constraint checking for extra-info descriptors
by atagar@torproject.org 14 May '12
by atagar@torproject.org 14 May '12
14 May '12
commit 234a90a79624e5503c4bf65db01c14e54fb9b8de
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 6 20:52:21 2012 -0700
Basic constraint checking for extra-info descriptors
Parsing the 'extra-info' line and performing basic validation about extra-info
descriptor fields (that we have required fields, most fields don't appear more
than once, etc).
I'll add some unit tests for this after I've added parsing for all of the
mandatory fields.
---
stem/descriptor/extrainfo_descriptor.py | 102 +++++++++++++++++++++++++++++++
stem/descriptor/server_descriptor.py | 4 +-
2 files changed, 104 insertions(+), 2 deletions(-)
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py
index 891ba18..04530c0 100644
--- a/stem/descriptor/extrainfo_descriptor.py
+++ b/stem/descriptor/extrainfo_descriptor.py
@@ -22,6 +22,52 @@ ExtraInfoDescriptor - Tor extra-info descriptor.
import stem.descriptor
+# relay descriptors must have exactly one of the following
+REQUIRED_FIELDS = (
+ "extra-info",
+ "published",
+ "router-signature",
+)
+
+# optional entries that can appear at most once
+SINGLE_FIELDS = (
+ "read-history",
+ "write-history",
+ "geoip-db-digest",
+ "bridge-stats-end",
+ "bridge-ips",
+ "dirreq-stats-end",
+ "dirreq-v2-ips",
+ "dirreq-v3-ips",
+ "dirreq-v2-reqs",
+ "dirreq-v3-reqs",
+ "dirreq-v2-share",
+ "dirreq-v3-share",
+ "dirreq-v2-resp",
+ "dirreq-v3-resp",
+ "dirreq-v2-direct-dl",
+ "dirreq-v3-direct-dl",
+ "dirreq-v2-tunneled-dl",
+ "dirreq-v3-tunneled-dl",
+ "dirreq-read-history",
+ "dirreq-write-history",
+ "entry-stats-end",
+ "entry-ips",
+ "cell-stats-end",
+ "cell-processed-cells",
+ "cell-queued-cells",
+ "cell-time-in-queue",
+ "cell-circuits-per-decile",
+ "conn-bi-direct",
+ "exit-stats-end",
+ "exit-kibibytes-written",
+ "exit-kibibytes-read",
+ "exit-streams-opened",
+)
+
+FIRST_FIELD = "extra-info"
+LAST_FIELD = "router-signature"
+
def parse_file(descriptor_file, validate = True):
"""
Iterates over the extra-info descriptors in a file.
@@ -108,4 +154,60 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor):
self.write_history_end = None
self.write_history_interval = None
self.write_history_values = []
+
+ entries, first_keyword, last_keyword, _ = \
+ stem.descriptor._get_descriptor_components(raw_contents, validate, ())
+
+ if validate:
+ for keyword in REQUIRED_FIELDS:
+ if not keyword in entries:
+ raise ValueError("Extra-info descriptor must have a '%s' entry" % keyword)
+
+ for keyword in REQUIRED_FIELDS + SINGLE_FIELDS:
+ if keyword in entries and len(entries[keyword]) > 1:
+ raise ValueError("The '%s' entry can only appear once in an extra-info descriptor" % keyword)
+ if not first_keyword == FIRST_FIELD:
+ raise ValueError("Extra-info descriptor must start with a '%s' entry" % FIRST_FIELD)
+
+ if not last_keyword == LAST_FIELD:
+ raise ValueError("Descriptor must end with a '%s' entry" % LAST_FIELD)
+
+ self._parse(entries, validate)
+
+ def _parse(self, entries, validate):
+ """
+ Parses a series of 'keyword => (value, pgp block)' mappings and applies
+ them as attributes.
+
+ Arguments:
+ entries (dict) - descriptor contents to be applied
+ validate (bool) - checks the validity of descriptor content if True
+
+ Raises:
+ ValueError if an error occures in validation
+ """
+
+ for keyword, values in entries.items():
+ # most just work with the first (and only) value
+ value, block_contents = values[0]
+
+ line = "%s %s" % (keyword, value) # original line
+ if block_contents: line += "\n%s" % block_contents
+
+ if keyword == "extra-info":
+ # "extra-info" Nickname Fingerprint
+ extra_info_comp = value.split()
+
+ if len(extra_info_comp) != 2:
+ if not validate: continue
+ raise ValueError("Extra-info line must have two values: %s" % line)
+
+ if validate:
+ if not stem.util.tor_tools.is_valid_nickname(extra_info_comp[0]):
+ raise ValueError("Extra-info line entry isn't a valid nickname: %s" % extra_info_comp[0])
+ elif not stem.util.tor_tools.is_valid_fingerprint(extra_info_comp[1]):
+ raise ValueError("Tor relay fingerprints consist of fourty hex digits: %s" % extra_info_comp[1])
+
+ self.nickname = extra_info_comp[0]
+ self.fingerprint = extra_info_comp[1]
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index b87ed2a..12b0728 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -543,11 +543,11 @@ class ServerDescriptor(stem.descriptor.Descriptor):
expected_first_keyword = self._first_keyword()
if expected_first_keyword and not first_keyword == expected_first_keyword:
- raise ValueError("Descriptor must start with a '%s' entry" % first_keyword)
+ raise ValueError("Descriptor must start with a '%s' entry" % expected_first_keyword)
expected_last_keyword = self._last_keyword()
if expected_last_keyword and not last_keyword == expected_last_keyword:
- raise ValueError("Descriptor must end with a '%s' entry" % last_keyword)
+ raise ValueError("Descriptor must end with a '%s' entry" % expected_last_keyword)
if not self.exit_policy:
raise ValueError("Descriptor must have at least one 'accept' or 'reject' entry")
1
0
commit 7930b74b6586220cd02ee816107a85fc1ba7e4ae
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 6 13:38:45 2012 -0700
Missed a few more 'version 3' labels
---
stem/descriptor/server_descriptor.py | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 6b53866..551835d 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -6,6 +6,7 @@ etc). This information is provided from a few sources...
- control port via 'GETINFO desc/*' queries
- the 'cached-descriptors' file in tor's data directory
- tor metrics, at https://metrics.torproject.org/data.html
+- directory authorities and mirrors via their DirPort
parse_file - Iterates over the server descriptors in a file.
ServerDescriptor - Tor server descriptor.
@@ -222,7 +223,7 @@ class ServerDescriptor(stem.descriptor.Descriptor):
def __init__(self, raw_contents, validate = True, annotations = None):
"""
- Version 3 server descriptor constructor, created from an individual relay's
+ Server descriptor constructor, created from an individual relay's
descriptor content (as provided by "GETINFO desc/*", cached descriptors,
and metrics).
@@ -602,7 +603,7 @@ class ServerDescriptor(stem.descriptor.Descriptor):
class RelayDescriptor(ServerDescriptor):
"""
- Version 3 server descriptor, as specified in...
+ Server descriptor, as specified in...
https://gitweb.torproject.org/torspec.git/blob/HEAD:/dir-spec.txt
Attributes:
@@ -697,7 +698,7 @@ class RelayDescriptor(ServerDescriptor):
class BridgeDescriptor(ServerDescriptor):
"""
- Version 3 bridge descriptor, as specified in...
+ Bridge descriptor, as specified in...
https://metrics.torproject.org/formats.html#bridgedesc
Attributes:
1
0
commit 77a498ae31d0c95d1cdaa88752965fcea870990d
Author: Damian Johnson <atagar(a)torproject.org>
Date: Mon May 7 09:23:09 2012 -0700
Unit tests for extrainfo descriptors
Few basic unit tests for extrainfo descriptors. These are done in a similar
fashion to the server descriptors. I'm highly tempted to refactor out some
common bits, but at present that would probably hurt code readability more than
it would help. This'll change if I keep using the same type of helpers for
descriptor unit tests.
---
run_tests.py | 2 +
stem/descriptor/extrainfo_descriptor.py | 8 ++
test/unit/descriptor/__init__.py | 2 +-
test/unit/descriptor/extrainfo_descriptor.py | 131 ++++++++++++++++++++++++++
4 files changed, 142 insertions(+), 1 deletions(-)
diff --git a/run_tests.py b/run_tests.py
index 818bfb8..bf2c2bc 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -21,6 +21,7 @@ import test.unit.socket.control_line
import test.unit.socket.control_message
import test.unit.descriptor.reader
import test.unit.descriptor.server_descriptor
+import test.unit.descriptor.extrainfo_descriptor
import test.unit.util.conf
import test.unit.util.connection
import test.unit.util.enum
@@ -94,6 +95,7 @@ UNIT_TESTS = (
test.unit.util.tor_tools.TestTorTools,
test.unit.descriptor.reader.TestDescriptorReader,
test.unit.descriptor.server_descriptor.TestServerDescriptor,
+ test.unit.descriptor.extrainfo_descriptor.TestExtraInfoDescriptor,
test.unit.version.TestVersion,
test.unit.socket.control_message.TestControlMessage,
test.unit.socket.control_line.TestControlLine,
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py
index fceaf60..e13787f 100644
--- a/stem/descriptor/extrainfo_descriptor.py
+++ b/stem/descriptor/extrainfo_descriptor.py
@@ -18,6 +18,7 @@ Extra-info descriptors are available from a few sources...
parse_file - Iterates over the extra-info descriptors in a file.
ExtraInfoDescriptor - Tor extra-info descriptor.
+ +- get_unrecognized_lines - lines with unrecognized content
"""
import datetime
@@ -159,6 +160,8 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor):
self.write_history_interval = None
self.write_history_values = []
+ self._unrecognized_lines = []
+
entries, first_keyword, last_keyword, _ = \
stem.descriptor._get_descriptor_components(raw_contents, validate, ())
@@ -178,6 +181,9 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor):
self._parse(entries, validate)
+ def get_unrecognized_lines(self):
+ return list(self._unrecognized_lines)
+
def _parse(self, entries, validate):
"""
Parses a series of 'keyword => (value, pgp block)' mappings and applies
@@ -227,4 +233,6 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor):
raise ValueError("Router signature line must be followed by a signature block: %s" % line)
self.signature = block_contents
+ else:
+ self._unrecognized_lines.append(line)
diff --git a/test/unit/descriptor/__init__.py b/test/unit/descriptor/__init__.py
index ae61cda..cf4fceb 100644
--- a/test/unit/descriptor/__init__.py
+++ b/test/unit/descriptor/__init__.py
@@ -2,5 +2,5 @@
Unit tests for stem.descriptor.
"""
-__all__ = ["reader", "server_descriptor"]
+__all__ = ["reader", "extrainfo_descriptor", "server_descriptor"]
diff --git a/test/unit/descriptor/extrainfo_descriptor.py b/test/unit/descriptor/extrainfo_descriptor.py
new file mode 100644
index 0000000..15ffe68
--- /dev/null
+++ b/test/unit/descriptor/extrainfo_descriptor.py
@@ -0,0 +1,131 @@
+"""
+Unit tests for stem.descriptor.extrainfo_descriptor.
+"""
+
+import unittest
+from stem.descriptor.extrainfo_descriptor import ExtraInfoDescriptor
+
+CRYPTO_BLOB = """
+K5FSywk7qvw/boA4DQcqkls6Ize5vcBYfhQ8JnOeRQC9+uDxbnpm3qaYN9jZ8myj
+k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw
+7LZqklu+gVvhMKREpchVqlAwXkWR44VENm24Hs+mT3M=
+"""
+
+EXTRAINFO_DESCRIPTOR_ATTR = (
+ ("extra-info", "ninja B2289C3EAB83ECD6EB916A2F481A02E6B76A0A48"),
+ ("published", "2012-05-05 17:03:50"),
+ ("router-signature", "\n-----BEGIN SIGNATURE-----%s-----END SIGNATURE-----" % CRYPTO_BLOB),
+)
+
+def _make_descriptor(attr = None, exclude = None):
+ """
+ Constructs a minimal extrainfo descriptor with the given attributes.
+
+ Arguments:
+ attr (dict) - keyword/value mappings to be included in the descriptor
+ exclude (list) - mandatory keywords to exclude from the descriptor
+
+ Returns:
+ str with customized descriptor content
+ """
+
+ descriptor_lines = []
+ if attr is None: attr = {}
+ if exclude is None: exclude = []
+ attr = dict(attr) # shallow copy since we're destructive
+
+ for keyword, value in EXTRAINFO_DESCRIPTOR_ATTR:
+ if keyword in exclude: continue
+ elif keyword in attr:
+ value = attr[keyword]
+ del attr[keyword]
+
+ # if this is the last entry then we should dump in any unused attributes
+ if keyword == "router-signature":
+ for attr_keyword, attr_value in attr.items():
+ descriptor_lines.append("%s %s" % (attr_keyword, attr_value))
+
+ descriptor_lines.append("%s %s" % (keyword, value))
+
+ return "\n".join(descriptor_lines)
+
+class TestExtraInfoDescriptor(unittest.TestCase):
+ def test_minimal_extrainfo_descriptor(self):
+ """
+ Basic sanity check that we can parse an extrainfo descriptor with minimal
+ attributes.
+ """
+
+ desc_text = _make_descriptor()
+ desc = ExtraInfoDescriptor(desc_text)
+
+ self.assertEquals("ninja", desc.nickname)
+ self.assertEquals("B2289C3EAB83ECD6EB916A2F481A02E6B76A0A48", desc.fingerprint)
+ self.assertTrue(CRYPTO_BLOB in desc.signature)
+
+ def test_unrecognized_line(self):
+ """
+ Includes unrecognized content in the descriptor.
+ """
+
+ desc_text = _make_descriptor({"pepperjack": "is oh so tasty!"})
+ desc = ExtraInfoDescriptor(desc_text)
+ self.assertEquals(["pepperjack is oh so tasty!"], desc.get_unrecognized_lines())
+
+ def test_proceeding_line(self):
+ """
+ Includes a line prior to the 'extra-info' entry.
+ """
+
+ desc_text = "exit-streams-opened port=80\n" + _make_descriptor()
+ self._expect_invalid_attr(desc_text)
+
+ def test_trailing_line(self):
+ """
+ Includes a line after the 'router-signature' entry.
+ """
+
+ desc_text = _make_descriptor() + "\nexit-streams-opened port=80"
+ self._expect_invalid_attr(desc_text)
+
+ def test_extrainfo_line_missing_fields(self):
+ """
+ Checks that validation catches when the extra-info line is missing fields
+ and that without validation both the nickname and fingerprint are left as
+ None.
+ """
+
+ test_entry = (
+ "ninja",
+ "ninja ",
+ "B2289C3EAB83ECD6EB916A2F481A02E6B76A0A48",
+ " B2289C3EAB83ECD6EB916A2F481A02E6B76A0A48",
+ )
+
+ for entry in test_entry:
+ desc_text = _make_descriptor({"extra-info": entry})
+ desc = self._expect_invalid_attr(desc_text, "nickname")
+ self.assertEquals(None, desc.nickname)
+ self.assertEquals(None, desc.fingerprint)
+
+ def _expect_invalid_attr(self, desc_text, attr = None, expected_value = None):
+ """
+ Asserts that construction will fail due to desc_text having a malformed
+ attribute. If an attr is provided then we check that it matches an expected
+ value when we're constructed without validation.
+ """
+
+ self.assertRaises(ValueError, ExtraInfoDescriptor, desc_text)
+ desc = ExtraInfoDescriptor(desc_text, validate = False)
+
+ if attr:
+ # check that the invalid attribute matches the expected value when
+ # constructed without validation
+
+ self.assertEquals(expected_value, getattr(desc, attr))
+ else:
+ # check a default attribute
+ self.assertEquals("ninja", desc.nickname)
+
+ return desc
+
1
0

[stem/master] Reverting change to recognize 127.0.0.1 as bridges
by atagar@torproject.org 14 May '12
by atagar@torproject.org 14 May '12
14 May '12
commit 9042c172f8544912888d174ab18b4a19882db7e3
Author: Damian Johnson <atagar(a)torproject.org>
Date: Mon May 7 09:27:06 2012 -0700
Reverting change to recognize 127.0.0.1 as bridges
Reverting change 477d448 since Karsten reports that bridges with that scrubbing
scheme should no longer exist.
---
stem/descriptor/server_descriptor.py | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 12b0728..8513b86 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -82,15 +82,14 @@ def parse_file(descriptor_file, validate = True):
# Handler for bridge descriptors
#
# Bridge descriptors are scrubbed so their nickname is 'Unnamed' and their
- # ip address is in the 10.x.x.x space (priorly '127.0.0.1'), which is
- # normally reserved for private networks. Bridge descriptors only come from
- # metrics so a file only contains a single descriptor.
+ # ip address is in the 10.x.x.x space, which is normally reserved for private
+ # networks. Bridge descriptors only come from metrics so a file only contains
+ # a single descriptor.
first_line = descriptor_file.readline()
descriptor_file.seek(0)
- if first_line.startswith("router Unnamed 10.") or \
- first_line.startswith("router Unnamed 127.0.0.1"):
+ if first_line.startswith("router Unnamed 10."):
yield BridgeDescriptor(descriptor_file.read())
return
1
0