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