📄 ipacl.cxx
字号:
/*
* ipacl.cxx
*
* IP Access Control Lists
*
* Portable Windows Library
*
* Copyright (c) 2002 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Contributor(s): ______________________________________.
*
* $Log: ipacl.cxx,v $
* Revision 1.1 2006/06/29 04:18:02 joegenbaclor
* *** empty log message ***
*
* Revision 1.16 2005/01/26 05:37:58 csoutheren
* Added ability to remove config file support
*
* Revision 1.15 2004/04/03 08:22:20 csoutheren
* Remove pseudo-RTTI and replaced with real RTTI
*
* Revision 1.14 2002/11/06 22:47:25 robertj
* Fixed header comment (copyright etc)
*
* Revision 1.13 2002/07/16 10:05:01 robertj
* Fixed GNU warning
*
* Revision 1.12 2002/07/16 10:02:49 robertj
* Fixed MSVC warning
*
* Revision 1.11 2002/07/16 09:58:51 robertj
* Fixed compatibility with unix htonl(), use platform independent function!
* Allow number of bits of 32 to be a full mask, ie a single host ip.
*
* Revision 1.10 2002/07/16 08:00:49 robertj
* Fixed correct endian-ness of mask when specifed in bits.
*
* Revision 1.9 2002/06/19 04:03:21 robertj
* Added default allowance boolean if ACL empty.
* Added ability to override the creation of ACL entry objects with descendents
* so an application can add information/functionality to each entry.
*
* Revision 1.8 2002/02/13 02:08:12 robertj
* Added const to IsAllowed() function.
* Added missing function that takes a socket.
*
* Revision 1.7 1999/02/25 13:01:11 robertj
* Fixed subtle bug in GNU compiler not automatically casting IP address.
*
* Revision 1.6 1999/02/25 11:10:52 robertj
* Fixed count of non-hidden entries in config file.
*
* Revision 1.5 1999/02/25 05:05:15 robertj
* Added missing test for hidden entries not to be written to config file
*
* Revision 1.4 1999/02/08 08:05:39 robertj
* Changed semantics of IP access control list for empty list.
*
* Revision 1.3 1999/01/31 10:14:07 robertj
* Changed about dialog to be full company name
*
* Revision 1.2 1999/01/31 08:10:33 robertj
* Fixed PConfig file save, out by one error in array subscript.
*
* Revision 1.1 1999/01/31 00:59:26 robertj
* Added IP Access Control List class to PTLib Components
*
*/
#include <ptlib.h>
#include <ptclib/ipacl.h>
#define new PNEW
PIpAccessControlEntry::PIpAccessControlEntry(PIPSocket::Address addr,
PIPSocket::Address msk,
BOOL allow)
: address(addr), mask(msk)
{
allowed = allow;
hidden = FALSE;
}
PIpAccessControlEntry::PIpAccessControlEntry(const PString & description)
: address(0), mask(0xffffffff)
{
Parse(description);
}
PIpAccessControlEntry & PIpAccessControlEntry::operator=(const PString & description)
{
Parse(description);
return *this;
}
PIpAccessControlEntry & PIpAccessControlEntry::operator=(const char * description)
{
Parse(description);
return *this;
}
PObject::Comparison PIpAccessControlEntry::Compare(const PObject & obj) const
{
PAssert(PIsDescendant(&obj, PIpAccessControlEntry), PInvalidCast);
const PIpAccessControlEntry & other = (const PIpAccessControlEntry &)obj;
// The larger the mask value, th more specific the range, so earlier in list
if (mask > other.mask)
return LessThan;
if (mask < other.mask)
return GreaterThan;
if (!domain && !other.domain)
return domain.Compare(other.domain);
if (address > other.address)
return LessThan;
if (address < other.address)
return GreaterThan;
return EqualTo;
}
void PIpAccessControlEntry::PrintOn(ostream & strm) const
{
if (!allowed)
strm << '-';
if (hidden)
strm << '@';
if (domain.IsEmpty())
strm << address;
else if (domain[0] != '\xff')
strm << domain;
else {
strm << "ALL";
return;
}
if (mask != 0 && mask != 0xffffffff)
strm << '/' << mask;
}
void PIpAccessControlEntry::ReadFrom(istream & strm)
{
char buffer[200];
strm >> ws >> buffer;
Parse(buffer);
}
BOOL PIpAccessControlEntry::Parse(const PString & description)
{
domain = PString();
address = 0;
if (description.IsEmpty())
return FALSE;
// Check for the allow/deny indication in first character of description
BOOL offset = 1;
if (description[0] == '-')
allowed = FALSE;
else {
allowed = TRUE;
if (description[0] != '+')
offset = 0;
}
// Check for indication entry is from the hosts.allow/hosts.deny file
hidden = FALSE;
if (description[offset] == '@') {
offset++;
hidden = TRUE;
}
if (description.Mid(offset) *= "all") {
domain = "\xff";
mask = 0;
return TRUE;
}
PINDEX slash = description.Find('/', offset);
PString preSlash = description(offset, slash-1);
if (preSlash[0] == '.') {
// If has a leading dot then assume a domain, ignore anything after slash
domain = preSlash;
mask = 0;
return TRUE;
}
if (strspn(preSlash, "0123456789.") != (size_t)preSlash.GetLength()) {
// If is not all numbers and dots can't be an IP number so assume hostname
domain = preSlash;
}
else if (preSlash[preSlash.GetLength()-1] != '.') {
// Must be explicit IP number if doesn't end in dot
address = preSlash;
}
else {
// Must be partial IP number, count the dots!
PINDEX dot = preSlash.Find('.', preSlash.Find('.')+1);
if (dot == P_MAX_INDEX) {
// One dot
preSlash += "0.0.0";
mask = "255.0.0.0";
}
else if ((dot = preSlash.Find('.', dot+1)) == P_MAX_INDEX) {
// has two dots
preSlash += "0.0";
mask = "255.255.0.0";
}
else if (preSlash.Find('.', dot+1) == P_MAX_INDEX) {
// has three dots
preSlash += "0";
mask = "255.255.255.0";
}
else {
// Has more than three dots!
return FALSE;
}
address = preSlash;
return TRUE;
}
if (slash == P_MAX_INDEX) {
// No slash so assume a full mask
mask = 0xffffffff;
return TRUE;
}
PString postSlash = description.Mid(slash+1);
if (strspn(postSlash, "0123456789.") != (size_t)postSlash.GetLength()) {
domain = PString();
address = 0;
return FALSE;
}
if (postSlash.Find('.') != P_MAX_INDEX)
mask = postSlash;
else {
DWORD bits = postSlash.AsUnsigned();
if (bits > 32)
mask = PSocket::Host2Net(bits);
else
mask = PSocket::Host2Net((DWORD)(0xffffffff << (32 - bits)));
}
if (mask == 0)
domain = "\xff";
address = (DWORD)address & (DWORD)mask;
return TRUE;
}
PString PIpAccessControlEntry::AsString() const
{
PStringStream str;
str << *this;
return str;
}
BOOL PIpAccessControlEntry::IsValid()
{
return address != 0 || !domain;
}
BOOL PIpAccessControlEntry::Match(PIPSocket::Address & addr)
{
switch (domain[0]) {
case '\0' : // Must have address field set
break;
case '.' : // Are a domain name
return PIPSocket::GetHostName(addr).Right(domain.GetLength()) *= domain;
case '\xff' : // Match all
return TRUE;
default : // All else must be a hostname
if (!PIPSocket::GetHostAddress(domain, address))
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -