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