home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 217 / DPCS0306DVD.ISO / Toolkit / Internet / FileZilla / Server / FileZilla_Server-0.9.11.exe / source / iputils.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-11-23  |  4.2 KB  |  163 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. #include "stdafx.h"
  20. #include "iputils.h"
  21. #include <boost/regex.hpp>
  22.  
  23. bool IsValidAddressFilter(CStdString& filter, bool allowWildcards /*=true*/)
  24. {
  25.     // Check for regular expression syntax (to match against the hostname).
  26.     if (filter.Left(1) == "/" && filter.Right(1) == "/")
  27.     {
  28.         if (filter.GetLength() < 3)
  29.             return false;
  30.  
  31.         try
  32.         {
  33.             boost::regex e(filter.Mid(1, filter.GetLength() - 2));
  34.         }
  35.         catch (std::runtime_error)
  36.         {
  37.             return false;
  38.         }
  39.         return true;
  40.     }
  41.  
  42.     if (filter.Find("..") != -1)
  43.         return false;
  44.  
  45.     // Check for IP/subnet syntax.
  46.     char chr = '/';
  47.     int pos = filter.Find(chr);
  48.     if (pos == -1)
  49.     {
  50.         // Check for IP range syntax.
  51.         chr = '-';
  52.         pos = filter.Find(chr);
  53.     }
  54.     if (pos != -1)
  55.     {
  56.         // Only one slash or dash is allowed.
  57.         CStdString right = filter.Mid(pos + 1);
  58.         if (right.Find('/') != -1 || right.Find('-') != -1)
  59.             return false;
  60.  
  61.         // When using IP/subnet or IP range syntax, no wildcards are allowed.
  62.         if (!IsValidAddressFilter(right, false))
  63.             return false;
  64.         CStdString left = filter.Left(pos);
  65.         if (!IsValidAddressFilter(left, false))
  66.             return false;
  67.  
  68.         filter = left + chr + right;
  69.     }
  70.     else
  71.     {
  72.         int dotCount = 0;
  73.         for (const char *cur = filter; *cur; cur++)
  74.         {
  75.             // Check for valid characters.
  76.             if ((*cur < '0' || *cur > '9') && *cur != '.' && (!allowWildcards || (*cur != '*' && *cur != '?')))
  77.                 return false;
  78.             else
  79.             {
  80.                 // Count the number of contained dots.
  81.                 if (*cur == '.')
  82.                     dotCount++;
  83.             }
  84.         }
  85.         if (dotCount != 3 || filter.Right(1) == "." || filter.Left(1) == ".")
  86.             return false;
  87.     }
  88.  
  89.     // Merge redundant wildcards.
  90.     while (filter.Replace("?*", "*"));
  91.     while (filter.Replace("*?", "*"));
  92.     while (filter.Replace("**", "*"));
  93.  
  94.     return true;
  95. }
  96.  
  97. bool MatchesFilter(const CStdString& filter, unsigned int ip, const char* pIp)
  98. {
  99.     // ip and pIp are the same IP, one as number, the other one as string.
  100.  
  101.     // A single asterix matches all IPs.
  102.     if (filter == "*")
  103.         return true;
  104.  
  105.     // Check for regular expression filter.
  106.     if (filter.Left(1) == "/" && filter.Right(1) == "/")
  107.         return MatchesRegExp(filter.Mid(1, filter.GetLength() - 2), ntohl(ip));
  108.  
  109.     // Check for IP range syntax.
  110.     int pos2 = filter.Find('-');
  111.     if (pos2 != -1)
  112.     {
  113.         unsigned int min = htonl(inet_addr(filter.Left(pos2)));
  114.         unsigned int max = htonl(inet_addr(filter.Mid(pos2 + 1)));
  115.         return (ip >= min) && (ip <= max);
  116.     }
  117.  
  118.     // Check for IP/subnet syntax.
  119.     pos2 = filter.Find('/');
  120.     if (pos2 != -1)
  121.     {
  122.         unsigned int ip2 = htonl(inet_addr(filter.Left(pos2)));
  123.         unsigned int mask = htonl(inet_addr(filter.Mid(pos2 + 1)));
  124.         return (ip & mask) == (ip2 & mask);
  125.     }
  126.  
  127.     // Validate the IP address.
  128.     LPCTSTR c = filter;
  129.     LPCTSTR p = pIp;
  130.  
  131.     // Look if remote and local IP match.
  132.     while (*c && *p)
  133.     {
  134.         if (*c == '*')
  135.         {
  136.             if (*p == '.')
  137.                 break;
  138.  
  139.             // Advance to the next dot.
  140.             while (*p && *p != '.')
  141.                 p++;
  142.             c++;
  143.             continue;
  144.         }
  145.         else if (*c != '?') // If it's '?', we don't have to compare.
  146.             if (*c != *p)
  147.                 break;
  148.         p++;
  149.         c++;
  150.     }
  151.     return (!*c) && (!*p);
  152. }
  153.  
  154. bool MatchesRegExp(const CStdString& filter, unsigned int addr)
  155. {
  156.     // If the IP could not be resolved to a hostname, return false.
  157.     HOSTENT *host = gethostbyaddr((char*)&addr, sizeof(addr), AF_INET);
  158.     if (!host)
  159.         return false;
  160.     boost::regex e(filter);
  161.     return regex_match(host->h_name, e);
  162. }
  163.