Vidalia 0.2.10

RouterStatus.cpp

Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If 
00004 **  you did not receive the LICENSE file with this file, you may obtain it
00005 **  from the Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.vidalia-project.net/. No part of Vidalia, including this file,
00007 **  may be copied, modified, propagated, or distributed except according to
00008 **  the terms described in the LICENSE file.
00009 */
00010 
00011 /* 
00012 ** \file RouterStatus.cpp
00013 ** \version $Id: RouterStatus.cpp 3735 2009-04-28 20:28:01Z edmanm $
00014 ** \brief Parses a blob of router status text from Tor
00015 */
00016 
00017 #include "RouterStatus.h"
00018 
00019 #include "stringutil.h"
00020 
00021 /** Defines the time format used when parsing the published date and time from
00022  * a router's status. */
00023 #define TIME_FORMAT  "yyyy-MM-dd HH:mm:ss"
00024 
00025 
00026 /** Constructor. Parses <b>status</b> for router status information. The given
00027  * string should match the router status entry format from Tor's dir-spec.txt.
00028  * The currently recognized lines are:
00029  *
00030  *  "r" SP nickname SP identity SP digest SP publication SP IP SP ORPort
00031  *      SP DirPort NL
00032  *  "s" SP Flags NL
00033  *
00034  * Unrecognized lines are currently ignored.
00035  *
00036  * */
00037 RouterStatus::RouterStatus(const QStringList &status)
00038 {
00039   bool ok;
00040 
00041   _valid = false;
00042   _flags = 0;
00043 
00044   foreach (QString line, status) {
00045     if (line.startsWith("r ")) {
00046       QStringList parts = line.split(" ", QString::SkipEmptyParts);
00047       if (parts.size() < 9)
00048         return;
00049 
00050       /* Nickname */
00051       _name = parts.at(1);
00052       /* Identity key digest */
00053       _id = base16_encode(QByteArray::fromBase64(parts.at(2).toAscii()));
00054       if (_id.isEmpty())
00055         return;
00056       /* Most recent descriptor digest */
00057       _digest = base16_encode(QByteArray::fromBase64(parts.at(3).toAscii()));
00058       if (_digest.isEmpty())
00059         return;
00060       /* Most recent publication date */
00061       _published = QDateTime::fromString(parts.at(4) + " " + parts.at(5),
00062                                          TIME_FORMAT);
00063       if (!_published.isValid())
00064         return;
00065       /* IP address */
00066       _ipAddress = QHostAddress(parts.at(6));
00067       if (_ipAddress.isNull())
00068         return;
00069       /* ORPort */
00070       _orPort = parts.at(7).toUInt(&ok);
00071       if (!ok)
00072         return;
00073       /* DirPort */
00074       _dirPort = parts.at(8).toUInt(&ok);
00075       if (!ok)
00076         return;
00077 
00078       _valid = true;
00079     } else if (line.startsWith("s ")) {
00080       /* Status flags */
00081       QStringList flags = line.split(" ", QString::SkipEmptyParts);
00082       flags.removeFirst(); /* Remove the "s" */
00083 
00084       foreach (QString flag, flags) {
00085         _flags |= flagValue(flag);
00086       }
00087     }
00088   }
00089 }
00090 
00091 /** Returns a Flags enum value for the given router status <b>flag</b>. If
00092  * <b>flag</b> is not recognized, then <i>Unknown</i> is returned. */
00093 RouterStatus::Flag
00094 RouterStatus::flagValue(const QString &flag)
00095 {
00096   if (!flag.compare("Authority", Qt::CaseInsensitive))
00097     return Authority;
00098   if (!flag.compare("BadExit", Qt::CaseInsensitive))
00099     return BadExit;
00100   if (!flag.compare("BadDirectory", Qt::CaseInsensitive))
00101     return BadDirectory;
00102   if (!flag.compare("Exit", Qt::CaseInsensitive))
00103     return Exit;
00104   if (!flag.compare("Fast", Qt::CaseInsensitive))
00105     return Fast;
00106   if (!flag.compare("Guard", Qt::CaseInsensitive))
00107     return Guard;
00108   if (!flag.compare("HSDir", Qt::CaseInsensitive))
00109     return HSDir;
00110   if (!flag.compare("Named", Qt::CaseInsensitive))
00111     return Named;
00112   if (!flag.compare("Running", Qt::CaseInsensitive))
00113     return Running;
00114   if (!flag.compare("Stable", Qt::CaseInsensitive))
00115     return Stable;
00116   if (!flag.compare("Valid", Qt::CaseInsensitive))
00117     return Valid;
00118   if (!flag.compare("V2Dir", Qt::CaseInsensitive))
00119     return V2Dir;
00120   if (!flag.compare("V3Dir", Qt::CaseInsensitive))
00121     return V3Dir;
00122   return Unknown; /* Unknown status flag */
00123 }
00124