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 you 00004 ** did not receive the LICENSE file with this file, you may obtain it from the 00005 ** 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 the 00008 ** terms described in the LICENSE file. 00009 */ 00010 00011 /* 00012 ** \file Policy.cpp 00013 ** \version $Id: Policy.cpp 3735 2009-04-28 20:28:01Z edmanm $ 00014 ** \brief Exit policy parsing 00015 */ 00016 00017 #include "Policy.h" 00018 00019 #include <QStringList> 00020 00021 00022 /** Default constructor. Creates an AcceptAll policy. */ 00023 Policy::Policy() 00024 { 00025 _action = Accept; 00026 _address = QHostAddress::Any; 00027 _fromPort = _toPort = 0; 00028 _mask = 0; 00029 } 00030 00031 /** Constructor. Creates a new Policy object from the given string. */ 00032 Policy::Policy(QString policy) 00033 { 00034 /* Set the defaults */ 00035 _action = Accept; 00036 _address = QHostAddress::Any; 00037 _fromPort = _toPort = 0; 00038 _mask = 0; 00039 00040 /* Parse the given string to override the defaults. */ 00041 fromString(policy); 00042 } 00043 00044 /** Constructor. Creates a new Policy object from the string parts. */ 00045 Policy::Policy(QString action, QString address, QString ports) 00046 { 00047 /* Set the defaults */ 00048 _action = Accept; 00049 _address = QHostAddress::Any; 00050 _fromPort = _toPort = 0; 00051 _mask = 0; 00052 00053 fromString(action + " " + address + ":" + ports); 00054 } 00055 00056 /** Constructor. Creates a new Policy object depending on the specified 00057 * special policy type. */ 00058 Policy::Policy(SpecialPolicy policy) 00059 { 00060 _action = (policy == AcceptAll ? Accept : Reject); 00061 _address = QHostAddress::Any; 00062 _fromPort = _toPort = 0; 00063 _mask = 0; 00064 } 00065 00066 /** Constructor. Creates a new policy object based on the given rules. */ 00067 Policy::Policy(Action action, QHostAddress addr, uchar mask, 00068 quint16 fromPort, quint16 toPort) 00069 { 00070 _action = action; 00071 _address = addr; 00072 _mask = mask; 00073 _fromPort = fromPort; 00074 _toPort = (toPort >= fromPort ? toPort : fromPort); 00075 } 00076 00077 /** Returns true if this policy is identical to <b>policy</b>. */ 00078 bool 00079 Policy::operator==(const Policy &policy) const 00080 { 00081 return ((this->_action == policy._action) && 00082 (this->_address == policy._address) && 00083 (this->_mask == policy._mask) && 00084 (this->_fromPort == policy._fromPort) && 00085 (this->_toPort == policy._toPort)); 00086 } 00087 00088 /** Returns true if this policy matches <b>policy</b>. For example, if this 00089 * policy is "reject *:6660-6669" and <b>policy</b> is "reject *:6662-6664", 00090 * this will return true. For strict comparison, use the == operator. */ 00091 bool 00092 Policy::matches(const Policy &policy) const 00093 { 00094 /* This doesn't take into account addr/mask matches yet */ 00095 return ((this->_action == policy._action) && 00096 (this->_address == policy._address) && 00097 (this->_mask == policy._mask) && 00098 (this->_fromPort <= policy._fromPort) && 00099 (this->_toPort >= policy._toPort)); 00100 } 00101 00102 /** Parses the given exit policy string. */ 00103 void 00104 Policy::fromString(QString policy) 00105 { 00106 /* Separate the action and the address/mask/port info */ 00107 QStringList ruleParts = policy.split(" "); 00108 _action = toAction(ruleParts.at(0)); 00109 00110 /* If some address/mask/port stuff was specified, parse it. */ 00111 if (ruleParts.size() > 1) { 00112 QStringList addrParts = ruleParts.at(1).split(":"); 00113 00114 /* Parse the address and mask (if specified) */ 00115 QString addr = addrParts.at(0); 00116 _address.setAddress(addr.mid(0, addr.indexOf("/"))); 00117 if (_address.isNull()) { 00118 _address = QHostAddress::Any; 00119 } 00120 if (addr.contains("/")) { 00121 _mask = addr.mid(addr.indexOf("/")+1).toUInt(); 00122 } 00123 00124 /* Parse the specified port range (if specified) */ 00125 if (addrParts.size() > 1) { 00126 QString ports = addrParts.at(1); 00127 _fromPort = ports.mid(0, ports.indexOf("-")).toUInt(); 00128 if (ports.contains("-")) { 00129 _toPort = ports.mid(ports.indexOf("-")+1).toUInt(); 00130 } else { 00131 _toPort = _fromPort; 00132 } 00133 } 00134 } 00135 } 00136 00137 /** Converts this policy to a form Tor understands. The format is: 00138 * "accept|reject ADDR[/MASK][:PORT]" 00139 * 00140 * PORT can be a single port number, an interval of ports "FROM_PORT-TO_PORT", 00141 * or "*". If PORT is omitted, that means "*" 00142 */ 00143 QString 00144 Policy::toString() const 00145 { 00146 QString act = (_action == Accept ? "accept" : "reject"); 00147 return act + " " + address() + ":" + ports(); 00148 } 00149 00150 /** Converts the given action to a string. This function tolerates both the 00151 * translated and untranslated forms of the string "accept" and "reject". */ 00152 Policy::Action 00153 Policy::toAction(QString action) 00154 { 00155 action = action.toLower(); 00156 if (action == tr("accept") || action == "accept") { 00157 return Accept; 00158 } 00159 return Reject; 00160 } 00161 00162 /** Returns the action associated with this policy. NOTE: This string will be 00163 * translated to whatever the current language setting is. */ 00164 QString 00165 Policy::action() const 00166 { 00167 return (_action == Accept ? tr("accept") : tr("reject")); 00168 } 00169 00170 /** Returns the address (and mask, if specified) for this policy. */ 00171 QString 00172 Policy::address() const 00173 { 00174 QString addrString; 00175 00176 if (_mask) { 00177 addrString = _address.toString() + "/" + QString::number(_mask); 00178 } else if (_address == QHostAddress::Any || _address.isNull()) { 00179 addrString = "*"; 00180 } else { 00181 addrString = _address.toString(); 00182 } 00183 return addrString; 00184 } 00185 00186 /** Returns the port (or port range, if specified) for this policy. */ 00187 QString 00188 Policy::ports() const 00189 { 00190 QString ports = (_fromPort ? QString::number(_fromPort) : "*"); 00191 if (_fromPort && (_toPort > _fromPort)) { 00192 ports += "-" + QString::number(_toPort); 00193 } 00194 return ports; 00195 } 00196