Vidalia
0.2.17
|
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