Vidalia  0.3.1
RouterStatus.cpp
Go to the documentation of this file.
1 /*
2 ** This file is part of Vidalia, and is subject to the license terms in the
3 ** LICENSE file, found in the top level directory of this distribution. If
4 ** you did not receive the LICENSE file with this file, you may obtain it
5 ** from the Vidalia source package distributed by the Vidalia Project at
6 ** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7 ** including this file, may be copied, modified, propagated, or distributed
8 ** except according to the terms described in the LICENSE file.
9 */
10 
11 /*
12 ** \file RouterStatus.cpp
13 ** \brief Parses a blob of router status text from Tor
14 */
15 
16 #include "RouterStatus.h"
17 
18 #include "stringutil.h"
19 
20 /** Defines the time format used when parsing the published date and time from
21  * a router's status. */
22 #define TIME_FORMAT "yyyy-MM-dd HH:mm:ss"
23 
24 
25 /** Constructor. Parses <b>status</b> for router status information. The given
26  * string should match the router status entry format from Tor's dir-spec.txt.
27  * The currently recognized lines are:
28  *
29  * "r" SP nickname SP identity SP digest SP publication SP IP SP ORPort
30  * SP DirPort NL
31  * "s" SP Flags NL
32  *
33  * Unrecognized lines are currently ignored.
34  *
35  * */
36 RouterStatus::RouterStatus(const QStringList &status)
37 {
38  bool ok;
39 
40  _valid = false;
41  _flags = 0;
42 
43  foreach (QString line, status) {
44  if (line.startsWith("r ")) {
45  QStringList parts = line.split(" ", QString::SkipEmptyParts);
46  if (parts.size() < 9)
47  return;
48 
49  /* Nickname */
50  _name = parts.at(1);
51  /* Identity key digest */
52  _id = base16_encode(QByteArray::fromBase64(parts.at(2).toAscii()));
53  if (_id.isEmpty())
54  return;
55  /* Most recent descriptor digest */
56  _digest = base16_encode(QByteArray::fromBase64(parts.at(3).toAscii()));
57  if (_digest.isEmpty())
58  return;
59  /* Most recent publication date */
60  _published = QDateTime::fromString(parts.at(4) + " " + parts.at(5),
61  TIME_FORMAT);
62  if (!_published.isValid())
63  return;
64  /* IP address */
65  _ipAddress = QHostAddress(parts.at(6));
66  if (_ipAddress.isNull())
67  return;
68  /* ORPort */
69  _orPort = parts.at(7).toUInt(&ok);
70  if (!ok)
71  return;
72  /* DirPort */
73  _dirPort = parts.at(8).toUInt(&ok);
74  if (!ok)
75  return;
76 
77  _valid = true;
78  } else if (line.startsWith("s ")) {
79  /* Status flags */
80  QStringList flags = line.split(" ", QString::SkipEmptyParts);
81  flags.removeFirst(); /* Remove the "s" */
82 
83  foreach (QString flag, flags) {
84  _flags |= flagValue(flag);
85  }
86  }
87  }
88 }
89 
90 /** Returns a Flags enum value for the given router status <b>flag</b>. If
91  * <b>flag</b> is not recognized, then <i>Unknown</i> is returned. */
93 RouterStatus::flagValue(const QString &flag)
94 {
95  if (!flag.compare("Authority", Qt::CaseInsensitive))
96  return Authority;
97  if (!flag.compare("BadExit", Qt::CaseInsensitive))
98  return BadExit;
99  if (!flag.compare("BadDirectory", Qt::CaseInsensitive))
100  return BadDirectory;
101  if (!flag.compare("Exit", Qt::CaseInsensitive))
102  return Exit;
103  if (!flag.compare("Fast", Qt::CaseInsensitive))
104  return Fast;
105  if (!flag.compare("Guard", Qt::CaseInsensitive))
106  return Guard;
107  if (!flag.compare("HSDir", Qt::CaseInsensitive))
108  return HSDir;
109  if (!flag.compare("Named", Qt::CaseInsensitive))
110  return Named;
111  if (!flag.compare("Running", Qt::CaseInsensitive))
112  return Running;
113  if (!flag.compare("Stable", Qt::CaseInsensitive))
114  return Stable;
115  if (!flag.compare("Valid", Qt::CaseInsensitive))
116  return Valid;
117  if (!flag.compare("V2Dir", Qt::CaseInsensitive))
118  return V2Dir;
119  if (!flag.compare("V3Dir", Qt::CaseInsensitive))
120  return V3Dir;
121  return Unknown; /* Unknown status flag */
122 }
123