Vidalia  0.2.15
Circuit.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.torproject.org/projects/vidalia.html. No part of Vidalia, 
00007 **  including this file, may be copied, modified, propagated, or distributed 
00008 **  except according to the terms described in the LICENSE file.
00009 */
00010 
00011 /* 
00012 ** \file Circuit.cpp
00013 ** \brief Object representing a Tor circuit
00014 */
00015 
00016 #include "tcglobal.h"
00017 #include "Circuit.h"
00018 
00019 #include <QStringList>
00020 #include <QRegExp>
00021 
00022 
00023 /** Default constructor. */
00024 Circuit::Circuit()
00025 {
00026   _status  = Unknown;
00027   _isValid = false;
00028 }
00029 
00030 /** Parses the string given in Tor control protocol format for a circuit. The
00031  * format is:
00032  * 
00033  *      CircuitID SP CircStatus [SP Path]
00034  *
00035  * If the status is "LAUNCHED", the Path is empty. Server names in the path
00036  * must follow Tor's VERBOSE_NAMES format.
00037  */
00038 Circuit::Circuit(const QString &circuit)
00039 {
00040   QStringList parts = circuit.split(" ", QString::SkipEmptyParts);
00041   if (parts.size() >= 2) {
00042     /* Get the circuit ID */
00043     _circId = parts.at(0);
00044     if (! isValidCircuitId(_circId))
00045       goto err;
00046 
00047     /* Get the circuit status value */
00048     _status = Circuit::toStatus(parts.at(1));
00049 
00050     /* Get the circuit path (list of routers) */
00051     if (parts.size() > 2 && parts.at(2).startsWith("$")) {
00052       foreach (QString hop, parts.at(2).split(",")) {
00053         QStringList parts = hop.split(QRegExp("[=~]"));
00054         if (parts.size() != 2)
00055           goto err;
00056 
00057         _ids   << parts.at(0).mid(1);
00058         _names << parts.at(1);
00059       }
00060     }
00061 
00062     _isValid = true;
00063   }
00064   return;
00065   
00066 err:
00067   tc::warn("Improperly formatted circuit: '%1'").arg(circuit);
00068   _isValid = false;
00069 }
00070 
00071 /** Returns true iff <b>circId</b> consists of only between 1 and 16
00072  * (inclusive) ASCII-encoded letters and numbers. */
00073 bool
00074 Circuit::isValidCircuitId(const CircuitId &circId)
00075 {
00076   int length = circId.length();
00077   if (length < 1 || length > 16)
00078     return false;
00079 
00080   for (int i = 0; i < length; i++) {
00081     char c = circId[i].toAscii();
00082     if (c < '0' && c > '9' && c < 'A' && c > 'Z' && c < 'a' && c > 'z')
00083       return false;
00084   }
00085   return true;
00086 }
00087 
00088 /** Converts the circuit status string to its proper enum value */
00089 Circuit::Status
00090 Circuit::toStatus(const QString &status)
00091 {
00092   if (!status.compare("LAUNCHED", Qt::CaseInsensitive))
00093     return Launched;
00094   if (!status.compare("BUILT", Qt::CaseInsensitive))
00095     return Built;
00096   if (!status.compare("EXTENDED", Qt::CaseInsensitive))
00097     return Extended;
00098   if (!status.compare("FAILED", Qt::CaseInsensitive))
00099     return Failed;
00100   if (!status.compare("CLOSED", Qt::CaseInsensitive))
00101     return Closed;
00102   return Unknown;
00103 }
00104 
00105 /** Returns a string representation of the circuit's status. */
00106 QString
00107 Circuit::statusString() const
00108 {
00109   QString status;
00110   switch (_status) {
00111     case Launched:    status = tr("New"); break;
00112     case Built:       status = tr("Open"); break;
00113     case Extended:    status = tr("Building"); break;
00114     case Failed:      status = tr("Failed");  break;
00115     case Closed:      status = tr("Closed"); break;
00116     default:          status = tr("Unknown"); break;
00117   }
00118   return status;
00119 }
00120