Based on 'rtorrent-0.8.5-ip_filter_no_boost-fast.patch' by Richard Monk and 'yb'
Adapted for rtorrent-0.8.6 by Denis Fateyev <denis@fateyev.com>
Adapted for rtorrent-0.8.7 by James Cuzella <james.cuzella@lyraphase.com>
Rev.2 (BSD/MacOSX support provided)

See http://libtorrent.rakshasa.no/ticket/239 for more details.

--- a/configure.ac
+++ b/configure.ac
@@ -4,6 +4,7 @@
 AM_CONFIG_HEADER(config.h)
 AM_PATH_CPPUNIT(1.9.6)
 
+AC_CHECK_FUNCS(getline)
 AC_PROG_CXX
 AC_PROG_LIBTOOL
 
--- a/configure.ac.orig
+++ b/configure.ac.orig
@@ -0,0 +1,68 @@
+AC_INIT(rtorrent, 0.8.7, jaris@ifi.uio.no)
+
+AM_INIT_AUTOMAKE
+AM_CONFIG_HEADER(config.h)
+AM_PATH_CPPUNIT(1.9.6)
+
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+
+TORRENT_CHECK_CXXFLAGS()
+TORRENT_ENABLE_DEBUG()
+TORRENT_ENABLE_EXTRA_DEBUG()
+TORRENT_ENABLE_WERROR()
+
+TORRENT_DISABLE_IPV6
+
+AC_SYS_LARGEFILE
+
+TORRENT_CHECK_EXECINFO()
+TORRENT_OTFD()
+
+TORRENT_ENABLE_ARCH
+TORRENT_WITH_SYSROOT
+
+TORRENT_WITHOUT_VARIABLE_FDSET()
+TORRENT_WITHOUT_NCURSESW()
+TORRENT_WITHOUT_STATVFS()
+TORRENT_WITHOUT_STATFS()
+
+PKG_CHECK_MODULES(sigc, sigc++-2.0,
+	          CXXFLAGS="$CXXFLAGS $sigc_CFLAGS";
+		  LIBS="$LIBS $sigc_LIBS")
+
+PKG_CHECK_MODULES(libcurl, libcurl >= 7.15.4,
+	          CXXFLAGS="$CXXFLAGS $libcurl_CFLAGS";
+		  LIBS="$LIBS $libcurl_LIBS")
+
+PKG_CHECK_MODULES(libtorrent, libtorrent >= 0.12.7,
+	          CXXFLAGS="$CXXFLAGS $libtorrent_CFLAGS";
+		  LIBS="$LIBS $libtorrent_LIBS")
+
+AC_LANG_PUSH(C++)
+TORRENT_WITH_XMLRPC_C
+AC_LANG_POP(C++)
+
+AC_DEFINE(HAVE_CONFIG_H, 1, true if config.h was included)
+AC_DEFINE(USER_AGENT, [std::string(PACKAGE "/" VERSION "/") + torrent::version()], Http user agent)
+
+AC_CHECK_FUNCS(posix_memalign)
+TORRENT_CHECK_CACHELINE()
+
+CC_ATTRIBUTE_UNUSED(
+	AC_DEFINE([__UNUSED], [__attribute__((unused))], [Wrapper around unused attribute]),
+	AC_DEFINE([__UNUSED], [], [Null-wrapper if unused attribute is unsupported])
+)
+
+AC_OUTPUT([
+	Makefile
+	doc/Makefile
+	src/Makefile
+	src/core/Makefile
+	src/display/Makefile
+	src/input/Makefile
+	src/rpc/Makefile
+	src/ui/Makefile
+	src/utils/Makefile
+        test/Makefile
+])

--- a/src/command_network.cc
+++ b/src/command_network.cc
@@ -36,6 +36,11 @@
 
 #include "config.h"
 
+#include <string>
+#include <sstream>
+#include <list>
+#include <unistd.h>
+
 #include <functional>
 #include <cstdio>
 #include <rak/address_info.h>
@@ -61,6 +66,10 @@
 #include "control.h"
 #include "command_helpers.h"
 
+#include "utils/pattern.h" 
+#include "core/ip_filter.h"
+
+
 torrent::Object
 apply_throttle(const torrent::Object::list_type& args, bool up) {
   torrent::Object::list_const_iterator argItr = args.begin();
@@ -202,6 +211,59 @@
   return torrent::Object();
 }
 
+ torrent::Object
+apply_ip_filter(const torrent::Object& rawArgs) {
+  const torrent::Object::list_type& args = rawArgs.as_list();
+
+  std::list<std::string> files;
+
+  for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
+    std::string file( itr->as_string() );
+    utils::trim( file );
+    if( access(file.c_str(),F_OK | R_OK) ) 
+      throw torrent::input_error("IpFilter file '" + file + "' does not exist or not readable. Filter could not be loaded");
+    files.push_back( file );
+  }
+
+  std::stringstream logMsg; 
+  if( files.empty() ) {
+    logMsg << "IpFilter is empty";
+    control->core()->push_log( logMsg.str().c_str() );
+  }
+  else {
+    core::IpFilter* f = new core::IpFilter();
+    logMsg << "IpFilter is initialized with files: ";
+    int entries = 0;
+    clock_t time_start = clock();
+    for( std::list<std::string>::iterator itr = files.begin(); itr != files.end(); itr++) {
+      std::cout << "Loading IP filters from '" << *itr << "'...";
+      std::cout.flush();
+      if( itr != files.begin() )
+        logMsg << ", ";
+      logMsg << *itr;
+      int merges = f->add_from_file( *itr );
+      if( merges < 0 ) {
+        std::cout << "error" << std::endl;
+        std::cout.flush();
+        throw torrent::input_error("IpFilter could not load file '" + *itr + "'");
+      }
+      std::cout << "done. Loaded " << (f->size()-entries) << " ranges. " << merges << " ranges were merged." << std::endl;
+      std::cout.flush();
+      entries = f->size();
+    }
+    control->core()->push_log( logMsg.str().c_str() );
+    std::stringstream logMsg2("IpFilter loaded with "); 
+    logMsg2 << f->size() << " ranges total. " << f->get_merges() << " ranges were merged.";
+    control->core()->push_log( logMsg2.str().c_str() );
+    std::cout << logMsg2.str() << std::endl;
+    std::cout << "IP_Filters loaded in " << (double)(clock()-time_start)/CLOCKS_PER_SEC << " seconds" << std::endl;
+    std::cout.flush();
+    control->core()->set_ip_filter( f );
+  }
+
+  return torrent::Object();
+}
+
 torrent::Object
 apply_tos(const torrent::Object::string_type& arg) {
   rpc::command_base::value_type value;
@@ -417,6 +479,10 @@
   torrent::FileManager* fileManager = torrent::file_manager();
   core::CurlStack* httpStack = control->core()->http_stack();
 
+  CMD2_ANY         ("reload_ip_filter", rak::make_mem_fun(control->core(), &core::Manager::reload_ip_filter));
+  CMD2_ANY_LIST    ("ip_filter", rak::ptr_fn(&apply_ip_filter));
+
+  
   CMD2_VAR_BOOL    ("log.handshake", false);
   CMD2_VAR_STRING  ("log.tracker",   "");
 

--- a/src/core/getline.cc
+++ b/src/core/getline.cc
@@ -0,0 +1,117 @@
+#include <string>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <errno.h>
+
+namespace core {
+
+/* getline.c ---  Implementation of replacement getline function.
+   Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free
+   Software Foundation, Inc.
+
+/* Ported from glibc by Simon Josefsson. */
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+#ifndef SSIZE_MAX
+# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+#endif
+#if !HAVE_FLOCKFILE
+# undef flockfile
+# define flockfile(x) ((void) 0)
+#endif
+#if !HAVE_FUNLOCKFILE
+# undef funlockfile
+# define funlockfile(x) ((void) 0)
+#endif
+
+/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
+   NUL-terminate it).  *LINEPTR is a pointer returned from malloc (or
+   NULL), pointing to *N characters of space.  It is realloc'ed as
+   necessary.  Returns the number of characters read (not including
+   the null terminator), or -1 on error or EOF.  */
+
+ssize_t getline (char **lineptr, size_t *n, FILE *fp)
+{
+  ssize_t result;
+  size_t cur_len = 0;
+
+  if (lineptr == NULL || n == NULL || fp == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  flockfile (fp);
+
+  if (*lineptr == NULL || *n == 0)
+    {
+      *n = 120;
+      *lineptr = (char *) malloc (*n);
+      if (*lineptr == NULL)
+{
+  result = -1;
+  goto unlock_return;
+}
+    }
+
+  for (;;)
+    {
+      int i;
+
+      i = getc (fp);
+      if (i == EOF)
+{
+  result = -1;
+  break;
+}
+
+      /* Make enough space for len+1 (for final NUL) bytes.  */
+      if (cur_len + 1 >= *n)
+{
+  size_t needed_max =
+    SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
+  size_t needed = 2 * *n + 1;   /* Be generous. */
+  char *new_lineptr;
+
+  if (needed_max < needed)
+    needed = needed_max;
+  if (cur_len + 1 >= needed)
+    {
+      result = -1;
+      goto unlock_return;
+    }
+
+  new_lineptr = (char *) realloc (*lineptr, needed);
+  if (new_lineptr == NULL)
+    {
+      result = -1;
+
+
+
+      goto unlock_return;
+    }
+
+  *lineptr = new_lineptr;
+  *n = needed;
+}
+
+      (*lineptr)[cur_len] = i;
+      cur_len++;
+
+      if (i == '\n')
+break;
+    }
+  (*lineptr)[cur_len] = '\0';
+  result = cur_len ? cur_len : result;
+
+ unlock_return:
+  funlockfile (fp);
+  return result;
+}
+
+}

--- a/src/core/getline.h
+++ b/src/core/getline.h
@@ -0,0 +1,25 @@
+#include <string>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <errno.h>
+
+namespace core {
+
+/* getline.c ---  Implementation of replacement getline function.
+   Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free
+   Software Foundation, Inc.
+
+/* Ported from glibc by Simon Josefsson. */
+
+/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
+   NUL-terminate it).  *LINEPTR is a pointer returned from malloc (or
+   NULL), pointing to *N characters of space.  It is realloc'ed as
+   necessary.  Returns the number of characters read (not including
+   the null terminator), or -1 on error or EOF.  */
+
+ssize_t getline (char **lineptr, size_t *n, FILE *fp);
+
+}

--- a/src/core/ip_address.cc
+++ b/src/core/ip_address.cc
@@ -0,0 +1,25 @@
+#include <cstdlib>
+#include <string>
+#include <arpa/inet.h>
+
+#include "ip_address.h"
+#include "utils/pattern.h"
+
+namespace core {
+
+std::pair<bool,uint32_t> IpAddress::to_int( const std::string& address ) {
+	uint32_t a;
+	int r = inet_pton( AF_INET, address.c_str(), &a);
+	if( r )
+		a = ntohl( a );
+	return std::pair<bool,uint32_t>( (r!=0), a );
+}
+
+std::string IpAddress::to_string() const {
+	char buf[128] = "";
+	uint32_t a = htonl( m_address );
+	inet_ntop( AF_INET, &a, buf, sizeof(buf) );
+	return std::string( buf );
+}
+
+}

--- a/src/core/ip_address.h
+++ b/src/core/ip_address.h
@@ -0,0 +1,65 @@
+#ifndef IPADDRESS_H
+#define IPADDRESS_H
+
+#include <inttypes.h> 
+#include <string>
+
+#include "printable.h"
+#include "utils/pattern.h"
+#include "regex_namespace.h"
+
+namespace core {
+
+class IpAddress : public Printable {
+	friend class IpRange;
+	
+	private: // constants
+		static const std::string	PATTERN_IP_EXPRESSION;
+		static const std::string	PATTERN_IP_BYTES_EXPRESSION;
+		static const regex::Pattern	PATTERN_IP_BYTES;
+
+		static const int		GRP_IP_FIRST_BYTE;
+		static const int		GRP_IP_BYTES_COUNT;
+
+	private: // fields
+		uint32_t			m_address;
+	
+	private: // static methods
+	
+	private: // dynamic methods
+		IpAddress() : m_address(0) {}
+	
+		void copy( const IpAddress& addr ) { m_address = addr.m_address;}
+	
+	public: // static methods
+		static std::pair<bool,uint32_t> to_int( const std::string& strAddress );
+		static IpAddress* parse( const std::string& strAddress ) {
+			std::pair<bool,uint32_t> result = to_int( strAddress );
+			return ( !result.first ) ? NULL : new IpAddress( result.second );
+		}
+	
+	public: // dynamic methods
+		IpAddress( uint32_t address ) : m_address(address) {}
+		IpAddress( const IpAddress& addr ) { copy( addr ); }
+		IpAddress& operator= ( const IpAddress& addr ) { copy( addr ); return *this; } 
+
+		operator uint32_t() const { return m_address; }
+
+		bool operator>= ( const IpAddress& ip ) const { return (m_address >=    ip.m_address); }
+		bool operator<= ( const IpAddress& ip ) const { return (m_address <=    ip.m_address); }
+		bool operator<  ( const IpAddress& ip ) const { return (m_address <     ip.m_address); }
+		bool operator>  ( const IpAddress& ip ) const { return (m_address >     ip.m_address); }
+		bool operator== ( const IpAddress& ip ) const { return (m_address ==    ip.m_address); }
+		bool operator!= ( const IpAddress& ip ) const { return (m_address !=    ip.m_address); }
+
+		bool operator>= ( uint32_t ip ) const { return (m_address >= ip); }
+		bool operator<= ( uint32_t ip ) const { return (m_address <= ip); }
+		bool operator<  ( uint32_t ip ) const { return (m_address <  ip); }
+		bool operator>  ( uint32_t ip ) const { return (m_address >  ip); }
+		bool operator== ( uint32_t ip ) const { return (m_address == ip); }
+		bool operator!= ( uint32_t ip ) const { return (m_address != ip); }
+
+		std::string to_string() const;
+	};
+}
+#endif

--- a/src/core/ip_filter.cc
+++ b/src/core/ip_filter.cc
@@ -0,0 +1,175 @@
+#include <sstream>
+#include <string>
+#include <map>
+#include <list>
+#include <fstream>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef __linux__
+#ifndef HAVE_GETLINE
+#include "getline.h"
+#endif
+#endif
+
+#include "ip_filter.h"
+
+namespace core {
+
+int IpFilter::merge_and_insert( range_map* rs, IpRange* r ) {
+	if( !r || !r->get_from() )
+		return 0;
+
+	std::pair<const IpAddress,IpRange::ptr> p( *r->get_from(), IpRange::ptr(r) );
+	std::pair<range_itr,bool> duo = rs->insert( p );
+
+	range_itr idx = duo.first;
+	bool wasInserted = duo.second;
+	IpRange* curr = NULL;
+	int mergeCount = 0;
+
+	if( !wasInserted ) { // exactly the same start address already exists
+		curr = idx->second;
+		if( *curr->get_to() < *r->get_to() )
+			curr->set_to( r->get_to() );
+		delete r;
+		r = curr;
+		mergeCount++;
+	}
+	else {
+		if( idx != rs->begin() ) {
+			--idx;
+		curr = idx->second; // previous
+		if( *r->get_from() <= *curr->get_to() )
+			r = curr;
+		else
+			++idx;
+		}
+	}
+
+	if( idx != rs->end() )
+		++idx;
+
+	while( idx != rs->end() ) {
+		curr = idx->second;
+		if( *r->get_to() < *curr->get_from() )
+			break;
+
+		std::string d = r->get_description();
+		d += " / " + curr->get_description();
+		r->set_description( d );
+		if( *r->get_to() < *curr->get_to() )
+			r->set_to( curr->get_to() );
+		rs->erase( idx++ );
+		delete curr;
+		mergeCount++;
+	}
+	return mergeCount;
+}
+
+int IpFilter::add_from_file( const std::string& fileName, range_map* rs, str_list* files ) {
+	FILE *f = fopen(fileName.c_str(),"r");
+	int mergeCount = 0;
+	if (f==0) return -1;
+	char *line = (char *)malloc(64);
+	size_t sz=64;
+	int charsread = 0;
+	int linesread=0;
+	while( (charsread=getline(&line,&sz,f)) >=0 ) {
+		if( (line[0] == '#' ) || ( charsread <= 1 ) ) 
+			continue;
+		
+		IpRange* ir = IpRange::parse( line, charsread );
+		if( !ir || !ir->get_from() || !ir->get_to() )
+			continue;
+
+		mergeCount += merge_and_insert( rs, ir );
+	}
+	free(line);
+	files->push_back( std::string(fileName) );
+	fclose(f);
+	m_merges += mergeCount;
+	return mergeCount;
+}
+
+int IpFilter::add_from_file( const std::string& fileName ) {
+	if( !m_ranges )
+		m_ranges = new range_map();
+	if( !m_loadedFiles )
+		m_loadedFiles = new std::list<std::string>();
+
+	return add_from_file( fileName, m_ranges, m_loadedFiles );
+}
+
+int IpFilter::reload() {
+	if( !m_loadedFiles || m_loadedFiles->empty() )
+		return 0;
+
+	range_map* rs = new range_map();
+	str_list* files = new str_list();
+	int mergeCount = 0;
+	for( str_list::const_iterator it = m_loadedFiles->begin(), end = m_loadedFiles->end(); it != end; it++ )
+		mergeCount += add_from_file( *it, rs, files );
+
+	range_map* rsOld = m_ranges;
+	m_ranges = rs;
+	if( rsOld ) {
+		clear( rsOld );
+		delete rsOld;
+	}
+
+	str_list* filesOld = m_loadedFiles;
+	m_loadedFiles = files;
+	if( filesOld ) {
+		clear( filesOld );
+		delete filesOld;
+	}
+
+	m_merges = mergeCount;
+	return mergeCount;
+}
+
+IpRange* IpFilter::find_range( uint32_t ip ) const {
+	if( (ip >= 0) && m_ranges && !m_ranges->empty() ) {
+		range_itr idx = m_ranges->upper_bound( ip );
+		if( idx != m_ranges->begin() )
+			--idx;
+		IpRange* curr = idx->second;
+		if( curr->includes( ip ) )
+			return curr;
+	}
+	return NULL;
+}
+
+std::string IpFilter::to_string() const {
+	std::stringstream result;
+	if( !m_ranges )
+		result << "NULL" << std::endl;
+	else {
+		for( range_map::const_iterator it = m_ranges->begin() ; it != m_ranges->end(); it++ ) {
+			const IpAddress a = it->first;
+			IpRange* ir = it->second;
+			result << a << ": " << *ir << std::endl;
+		}
+	}
+	return result.str();
+}
+
+void IpFilter::clear( range_map* map ) {
+	if( map ) {
+		for( range_itr i = map->begin(), j = map->end(); i != j; i++ )
+			delete i->second;
+		map->clear();
+	}
+}
+
+void IpFilter::clear( str_list* list ) {
+	if( list )
+		list->clear();
+}
+
+}

--- a/src/core/ip_filter.h
+++ b/src/core/ip_filter.h
@@ -0,0 +1,85 @@
+#ifndef IPFILTER_H
+#define IPFILTER_H
+
+#include <string>
+#include <map>
+#include <list>
+
+#include "printable.h"
+#include "ip_address.h"
+#include "ip_range.h"
+
+namespace core {
+
+typedef std::map<const IpAddress,IpRange::ptr>	range_map;
+typedef range_map::iterator			range_itr;
+typedef std::list<std::string>			str_list;
+
+class IpFilter : public Printable {
+	private: // fields
+		int m_merges;
+		range_map* m_ranges;
+		str_list* m_loadedFiles;
+
+	private: // static methods
+		static void clear( range_map* map );
+		static void clear( str_list* list );
+
+	private: // dynamic methods
+		void init_members(void) { // to avoid long constructor lines for every ctor
+			m_ranges = NULL;
+			m_loadedFiles = NULL;
+			m_merges = 0;
+		}
+		int merge_and_insert( range_map* rs, IpRange* r );
+		int add_from_file( const std::string& fileName, range_map* rs, str_list* files );
+
+	public: // static methods
+
+	public: // dynamic methods
+		IpFilter() { init_members(); }
+		~IpFilter() {
+			clear();
+			if( m_ranges ) delete m_ranges;
+			if( m_loadedFiles ) delete m_loadedFiles;
+			m_ranges = NULL;
+			m_loadedFiles = NULL;
+		}
+		IpFilter( std::string* files, int size ) {
+			init_members();
+			for( int i = 0; i < size; i++, files++ )
+				add_from_file( *files );
+		}
+		IpFilter( str_list& files ) {
+			init_members();
+			for( str_list::const_iterator i = files.begin(), last = files.end(); i != last; i++ )
+				add_from_file( *i );
+		}
+		IpFilter( IpFilter& f ) {
+			init_members();
+			m_ranges = new range_map( *f.m_ranges );
+			m_loadedFiles = new str_list( *f.m_loadedFiles );
+		}
+
+		int reload();
+		int add_from_file( const std::string& fileName );
+		int add_from_file( char* fileName ) { std::string s( fileName ); return add_from_file(s); }
+		void clear() { clear( m_ranges ); clear( m_loadedFiles ); }
+
+		IpRange* find_range( uint32_t ip ) const;
+
+		bool is_filtered( uint32_t ip ) const { return (find_range( ip ) != NULL); }
+		bool is_filtered( std::string ip ) const { 
+			static std::pair<bool,uint32_t> ipInt = IpAddress::to_int( ip );
+			return (!ipInt.first ? false : is_filtered( ipInt.second )); 
+		}
+
+		std::string to_string() const;
+
+		int size(void) { return ( m_ranges ? m_ranges->size() : 0 ); }
+		int get_merges(void) { return m_merges; }
+		void set_files( str_list& files) { m_loadedFiles = new str_list( files ); }
+};
+
+}
+#endif

--- a/src/core/ip_filter_statics.cc
+++ b/src/core/ip_filter_statics.cc
@@ -0,0 +1,21 @@
+#include "ip_address.h"
+#include "ip_range.h"
+#include "utils/pattern.h"
+
+namespace core {
+
+const std::string		IpAddress::PATTERN_IP_EXPRESSION		= "(([0-9]{1,3}\\.){3}[0-9]{1,3})";
+const std::string		IpAddress::PATTERN_IP_BYTES_EXPRESSION		= "([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})";
+const regex::Pattern		IpAddress::PATTERN_IP_BYTES			= PATTERN_IP_BYTES_EXPRESSION;
+
+const int			IpAddress::GRP_IP_FIRST_BYTE			= 1;
+const int			IpAddress::GRP_IP_BYTES_COUNT			= 4;
+
+const std::string		IpRange::PATTERN_RANGE_EXPRESSION		= "[[:space:]]*(.*)[[:space:]]*:[[:space:]]*" + IpAddress::PATTERN_IP_EXPRESSION + "[[:space:]]*-[[:space:]]*" + IpAddress::PATTERN_IP_EXPRESSION + "[[:space:]]*";
+const regex::Pattern		IpRange::PATTERN_RANGE				= PATTERN_RANGE_EXPRESSION;
+
+const int			IpRange::GRP_DESCRIPTION			= 1;
+const int			IpRange::GRP_FIRST_IP				= 2;
+const int			IpRange::GRP_SECOND_IP				= 4;
+
+}

--- a/src/core/ip_range.cc
+++ b/src/core/ip_range.cc
@@ -0,0 +1,112 @@
+#include <sstream>
+#include <string>
+
+#include "ip_range.h"
+#include "utils/pattern.h"
+#include "regex_namespace.h"
+
+namespace core {
+
+IpRange* IpRange::parse( const std::string& s ) {
+	regex::Match m = PATTERN_RANGE.match( s );
+		
+	if( !m.matches() ) {
+		std::cout << "!! range format is invalid: '" << s << "'" << std::endl;
+		return NULL;
+	}
+
+	std::string     description     = m.group( GRP_DESCRIPTION );
+	std::string     ip1             = m.group( GRP_FIRST_IP );
+	std::string     ip2             = m.group( GRP_SECOND_IP );
+	IpAddress*      from            = IpAddress::parse( ip1 );
+	IpAddress*      to              = IpAddress::parse( ip2 );
+
+	if( !from ) {
+		std::cout << "!! from is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl;
+		return NULL;
+	}
+	if( !to ) {
+		std::cout << "!! to is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl;
+		return NULL;
+	}
+
+//	if( !from || !to || (*to < *from) )
+//		return NULL;
+
+	IpRange* r = new IpRange();
+
+	r->m_description        = description;
+	r->m_from               = from;
+	r->m_to                 = to;
+
+	if( to && from && (*to < *from) ) {
+		std::cout << "!! to < from: " << r->to_string() << std::endl;
+		delete r;
+		return NULL;
+	}
+
+	return r;
+}
+
+//fast version
+IpRange* IpRange::parse( const char *s, const int size ){
+	static char description[256];
+	static char ip1[24], ip2[24];
+	int pos=0, post=0, enddesc=size-1;
+	while (enddesc>0 && s[enddesc]!=':') enddesc--; //find last ':' in the line
+	while((pos<enddesc) && (unsigned char)s[pos]<=' ') pos++; // strip from start
+	while ((pos<enddesc)){
+	  if (post<255) description[post++]=s[pos];
+	  pos++;
+	} 
+	description[post]=0;
+	if (s[pos]==':') pos++;
+	  post=0;
+	  while ((pos<size) && s[pos]!='-'){
+	    if (post<23) ip1[post++]=s[pos];
+	    pos++;
+	  } 
+	  ip1[post]=0;
+	  if (s[pos]=='-'){
+	    pos++;
+	    post=0;
+		while ((pos<size) && s[pos]>' '){
+	      if (post<23) ip2[post++]=s[pos];
+	      pos++;
+		}
+		ip2[post]=0;
+	  } else ip2[0]=0;
+
+	IpAddress*      from            = IpAddress::parse(ip1);
+	IpAddress*      to            = IpAddress::parse(ip2);
+
+	if( !from ) {
+		std::cout << "!! from is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl;
+		return NULL;
+	}
+	if( !to ) {
+		std::cout << "!! to is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl;
+		return NULL;
+	}
+
+	IpRange* r = new IpRange();
+	r->m_description        = description;
+	r->m_from               = from;
+	r->m_to                 = to;
+
+	if( (*to < *from) ) {
+		std::cout << "!! to < from: " << r->to_string() << std::endl;
+		delete r;
+		return NULL;
+	}
+	
+	return r;
+}
+
+std::string IpRange::to_string() const {
+	std::stringstream result;
+	result << m_description << ": [" << m_from->to_string() << " - " << m_to->to_string() << ']';
+	return result.str();
+}
+
+}

--- a/src/core/ip_range.h
+++ b/src/core/ip_range.h
@@ -0,0 +1,67 @@
+#ifndef IPRANGE_H
+#define IPRANGE_H
+
+#include <string>
+
+#include "printable.h"
+#include "ip_address.h"
+#include "utils/pattern.h"
+#include "regex_namespace.h"
+
+namespace core {
+
+class IpRange : public Printable {
+	public: // constants
+		static const std::string	PATTERN_RANGE_EXPRESSION;
+		static const regex::Pattern	PATTERN_RANGE;
+
+		static const int			GRP_DESCRIPTION;
+		static const int			GRP_FIRST_IP;
+		static const int			GRP_SECOND_IP;
+
+	private: // fields
+		std::string					m_description;
+		const IpAddress*			m_from;
+		const IpAddress*			m_to;
+
+	private: // dynamic methods
+		IpRange() : m_description(), m_from(NULL), m_to(NULL) {}
+	
+	public: // static methods
+		typedef IpRange* ptr;
+		static IpRange* parse( const std::string& s );
+		static IpRange* parse( const char *s, const int size );
+	
+	public: // dynamic methods
+		IpRange( IpRange& rng ) { copy(rng); }
+		IpRange& operator= ( IpRange& rng ) { copy(rng); return *this; }
+	
+		void copy( IpRange& rng ) {
+			m_description = rng.m_description;
+			m_from = (!rng.m_from) ? NULL : new IpAddress( *rng.m_from );
+			m_to = (!rng.m_to) ? NULL : new IpAddress( *rng.m_to );
+		}
+	
+		const std::string&      get_description ( void ) const  { return m_description; }
+		const IpAddress*        get_from        ( void ) const  { return m_from; }
+		const IpAddress*        get_to          ( void ) const  { return m_to; }
+		
+		void    set_description ( const std::string&    description )   { m_description = description; }
+		void    set_from        ( const IpAddress*      from )          { if( m_from ) delete m_from; m_from = new IpAddress( *from ); }
+		void    set_to          ( const IpAddress*      to )            { if( m_to ) delete m_to; m_to = new IpAddress( *to ); }
+		
+		bool    includes( const IpAddress& ip ) const { return includes((uint32_t)ip); }
+		bool    includes( uint32_t ip ) const { return (*m_from <= ip) && (*m_to >= ip); }
+		
+		~IpRange() {
+			delete m_from;
+			m_from = NULL;
+			delete m_to;
+			m_to = NULL;
+		}
+
+	std::string to_string() const;
+};
+
+}
+#endif

--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -36,6 +36,17 @@
 	view.cc \
 	view.h \
 	view_manager.cc \
-	view_manager.h
+	view_manager.h \
+	ip_address.cc \
+	ip_address.h \
+	ip_filter.cc \
+	ip_filter.h \
+	ip_range.cc \
+	ip_range.h \
+	printable.h \
+	regex_namespace.h \
+	ip_filter_statics.cc \
+	getline.h \
+	getline.cc
 
 INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)

--- a/src/core/Makefile.in
+++ b/src/core/Makefile.in
@@ -63,7 +63,12 @@
 	manager.$(OBJEXT) poll_manager.$(OBJEXT) \
 	poll_manager_epoll.$(OBJEXT) poll_manager_kqueue.$(OBJEXT) \
 	poll_manager_select.$(OBJEXT) view.$(OBJEXT) \
-	view_manager.$(OBJEXT)
+	view_manager.$(OBJEXT) \
+	ip_address.$(OBJEXT) \
+	ip_filter.$(OBJEXT) \
+	ip_range.$(OBJEXT) \
+	ip_filter_statics.$(OBJEXT) \
+	getline.$(OBJEXT)
 libsub_core_a_OBJECTS = $(am_libsub_core_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -256,7 +261,18 @@
 	view.cc \
 	view.h \
 	view_manager.cc \
-	view_manager.h
+	view_manager.h \
+	ip_address.cc \
+	ip_address.h \
+	ip_filter.cc \
+	ip_filter.h \
+	ip_range.cc \
+	ip_range.h \
+	printable.h \
+	regex_namespace.h \
+	ip_filter_statics.cc \
+	getline.cc \
+	getline.h
 
 INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)
 all: all-am
@@ -324,6 +340,10 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll_manager_select.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view_manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_address.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_range.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_filter_statics.Po@am__quote@  
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getline.Po@am__quote@
 
 .cc.o:
 @am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<

--- a/src/core/Makefile.in.orig
+++ b/src/core/Makefile.in.orig
@@ -0,0 +1,555 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/core
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/scripts/attributes.m4 \
+	$(top_srcdir)/scripts/checks.m4 \
+	$(top_srcdir)/scripts/common.m4 \
+	$(top_srcdir)/scripts/libtool.m4 \
+	$(top_srcdir)/scripts/ltoptions.m4 \
+	$(top_srcdir)/scripts/ltsugar.m4 \
+	$(top_srcdir)/scripts/ltversion.m4 \
+	$(top_srcdir)/scripts/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libsub_core_a_AR = $(AR) $(ARFLAGS)
+libsub_core_a_LIBADD =
+am_libsub_core_a_OBJECTS = curl_get.$(OBJEXT) curl_socket.$(OBJEXT) \
+	curl_stack.$(OBJEXT) dht_manager.$(OBJEXT) download.$(OBJEXT) \
+	download_factory.$(OBJEXT) download_list.$(OBJEXT) \
+	download_store.$(OBJEXT) http_queue.$(OBJEXT) log.$(OBJEXT) \
+	manager.$(OBJEXT) poll_manager.$(OBJEXT) \
+	poll_manager_epoll.$(OBJEXT) poll_manager_kqueue.$(OBJEXT) \
+	poll_manager_select.$(OBJEXT) view.$(OBJEXT) \
+	view_manager.$(OBJEXT)
+libsub_core_a_OBJECTS = $(am_libsub_core_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libsub_core_a_SOURCES)
+DIST_SOURCES = $(libsub_core_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
+CPPUNIT_CONFIG = @CPPUNIT_CONFIG@
+CPPUNIT_LIBS = @CPPUNIT_LIBS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libcurl_CFLAGS = @libcurl_CFLAGS@
+libcurl_LIBS = @libcurl_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libtorrent_CFLAGS = @libtorrent_CFLAGS@
+libtorrent_LIBS = @libtorrent_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sigc_CFLAGS = @sigc_CFLAGS@
+sigc_LIBS = @sigc_LIBS@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = libsub_core.a
+libsub_core_a_SOURCES = \
+	curl_get.cc \
+	curl_get.h \
+	curl_socket.cc \
+	curl_socket.h \
+	curl_stack.cc \
+	curl_stack.h \
+	dht_manager.cc \
+	dht_manager.h \
+	download.cc \
+	download.h \
+	download_factory.cc \
+	download_factory.h \
+	download_list.cc \
+	download_list.h \
+	download_slot_map.h \
+	download_store.cc \
+	download_store.h \
+	http_queue.cc \
+	http_queue.h \
+	log.cc \
+	log.h \
+	manager.cc \
+	manager.h \
+	poll_manager.cc \
+	poll_manager.h \
+	poll_manager_epoll.cc \
+	poll_manager_epoll.h \
+	poll_manager_kqueue.cc \
+	poll_manager_kqueue.h \
+	poll_manager_select.cc \
+	poll_manager_select.h \
+	range_map.h \
+	view.cc \
+	view.h \
+	view_manager.cc \
+	view_manager.h
+
+INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/core/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/core/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libsub_core.a: $(libsub_core_a_OBJECTS) $(libsub_core_a_DEPENDENCIES) 
+	-rm -f libsub_core.a
+	$(libsub_core_a_AR) libsub_core.a $(libsub_core_a_OBJECTS) $(libsub_core_a_LIBADD)
+	$(RANLIB) libsub_core.a
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curl_get.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curl_socket.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curl_stack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dht_manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/download.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/download_factory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/download_list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/download_store.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_queue.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll_manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll_manager_epoll.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll_manager_kqueue.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll_manager_select.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view_manager.Po@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

--- a/src/core/manager.cc
+++ b/src/core/manager.cc
@@ -153,6 +153,24 @@
   }
 }
 
+uint32_t
+Manager::filter_ip(const sockaddr* sa) {
+  IpRange* r = NULL;
+  // if something's wrong with filter or address it's gonna be allowed
+  if( m_ipFilter && sa ) {
+    const rak::socket_address* socketAddress = rak::socket_address::cast_from(sa);
+    if( socketAddress->is_valid() && (socketAddress->family() == rak::socket_address::af_inet) )
+      r = m_ipFilter->find_range( socketAddress->sa_inet()->address_h() );
+    if( r )
+      m_logComplete.push_front("Address '" + socketAddress->address_str() + "' is rejected by IP filter range '" + r->to_string());
+    else
+    if( rpc::call_command_value("get_handshake_log") )
+      m_logComplete.push_front("IP Filter allowed connection with '" + socketAddress->address_str() + "'");
+  }
+  return (r==NULL);
+}
+
+
 void
 Manager::push_log(const char* msg) {
   m_logImportant.push_front(msg);
@@ -160,7 +178,8 @@
 }
 
 Manager::Manager() :
-  m_hashingView(NULL)
+  m_hashingView(NULL),
+  m_ipFilter(NULL)
 //   m_pollManager(NULL) {
 {
   m_downloadStore   = new DownloadStore();
@@ -181,6 +200,8 @@
   delete m_downloadStore;
   delete m_httpQueue;
   delete m_fileStatusCache;
+
+  set_ip_filter( NULL );
 }
 
 void
@@ -226,6 +247,7 @@
   CurlStack::global_init();
 
   torrent::connection_manager()->set_signal_handshake_log(sigc::mem_fun(this, &Manager::handshake_log));
+  torrent::connection_manager()->set_filter(sigc::mem_fun(this, &Manager::filter_ip));
 }
 
 void
@@ -585,4 +607,14 @@
   }
 }
 
+void Manager::reload_ip_filter(void) {
+  if( m_ipFilter ) {
+    push_log("Reloading IP filter");
+    m_ipFilter->reload();
+    std::stringstream logMsg("IpFilter reloaded with "); 
+    logMsg << m_ipFilter->size() << " ranges total. " << m_ipFilter->get_merges() << " ranges were merged.";
+    push_log( logMsg.str().c_str() );
+  }
+}
+
 }

--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -47,6 +47,8 @@
 #include "range_map.h"
 #include "log.h"
 
+#include "ip_filter.h"
+
 namespace torrent {
   class Bencode;
 }
@@ -118,6 +120,15 @@
 
   void                handshake_log(const sockaddr* sa, int msg, int err, const torrent::HashString* hash);
 
+  uint32_t            filter_ip(const sockaddr* sa);
+
+  void                set_ip_filter( IpFilter* ipFilter ) {
+                        IpFilter* old = m_ipFilter;
+                        m_ipFilter = ipFilter;
+                        if( old ) delete old;
+                      }
+  void                reload_ip_filter(void);
+
   static const int create_start    = 0x1;
   static const int create_tied     = 0x2;
   static const int create_quiet    = 0x4;
@@ -154,6 +165,8 @@
 
   Log                 m_logImportant;
   Log                 m_logComplete;
+
+  IpFilter*           m_ipFilter;
 };
 
 // Meh, cleanup.

--- a/src/core/manager.h.orig
+++ b/src/core/manager.h.orig
@@ -0,0 +1,164 @@
+// rTorrent - BitTorrent client
+// Copyright (C) 2005-2007, Jari Sundell
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// In addition, as a special exception, the copyright holders give
+// permission to link the code of portions of this program with the
+// OpenSSL library under certain conditions as described in each
+// individual source file, and distribute linked combinations
+// including the two.
+//
+// You must obey the GNU General Public License in all respects for
+// all of the code used other than OpenSSL.  If you modify file(s)
+// with this exception, you may extend this exception to your version
+// of the file(s), but you are not obligated to do so.  If you do not
+// wish to do so, delete this exception statement from your version.
+// If you delete this exception statement from all source files in the
+// program, then also delete it here.
+//
+// Contact:  Jari Sundell <jaris@ifi.uio.no>
+//
+//           Skomakerveien 33
+//           3185 Skoppum, NORWAY
+
+#ifndef RTORRENT_CORE_MANAGER_H
+#define RTORRENT_CORE_MANAGER_H
+
+#include <iosfwd>
+#include <vector>
+
+#include <torrent/connection_manager.h>
+
+#include "download_list.h"
+#include "poll_manager.h"
+#include "range_map.h"
+#include "log.h"
+
+namespace torrent {
+  class Bencode;
+}
+
+namespace utils {
+class FileStatusCache;
+}
+
+namespace core {
+
+class DownloadStore;
+class HttpQueue;
+
+typedef std::map<std::string, torrent::ThrottlePair> ThrottleMap;
+
+class View;
+
+class Manager {
+public:
+  typedef DownloadList::iterator                    DListItr;
+  typedef utils::FileStatusCache                    FileStatusCache;
+
+  typedef sigc::slot1<void, DownloadList::iterator> SlotReady;
+  typedef sigc::slot0<void>                         SlotFailed;
+
+  Manager();
+  ~Manager();
+
+  DownloadList*       download_list()                     { return m_downloadList; }
+  DownloadStore*      download_store()                    { return m_downloadStore; }
+  FileStatusCache*    file_status_cache()                 { return m_fileStatusCache; }
+
+  HttpQueue*          http_queue()                        { return m_httpQueue; }
+  CurlStack*          http_stack()                        { return m_httpStack; }
+
+  View*               hashing_view()                      { return m_hashingView; }
+  void                set_hashing_view(View* v);
+
+  Log&                get_log_important()                 { return m_logImportant; }
+  Log&                get_log_complete()                  { return m_logComplete; }
+
+  ThrottleMap&          throttles()                       { return m_throttles; }
+  torrent::ThrottlePair get_throttle(const std::string& name);
+
+  // Use custom throttle for the given range of IP addresses.
+  void                  set_address_throttle(uint32_t begin, uint32_t end, torrent::ThrottlePair throttles);
+  torrent::ThrottlePair get_address_throttle(const sockaddr* addr);
+
+  // Really should find a more descriptive name.
+  void                initialize_second();
+  void                cleanup();
+
+  void                listen_open();
+
+  std::string         bind_address() const;
+  void                set_bind_address(const std::string& addr);
+
+  std::string         local_address() const;
+  void                set_local_address(const std::string& addr);
+
+  std::string         proxy_address() const;
+  void                set_proxy_address(const std::string& addr);
+
+  void                shutdown(bool force);
+
+  void                push_log(const char* msg);
+  void                push_log_std(const std::string& msg) { m_logImportant.push_front(msg); m_logComplete.push_front(msg); }
+  void                push_log_complete(const std::string& msg) { m_logComplete.push_front(msg); }
+
+  void                handshake_log(const sockaddr* sa, int msg, int err, const torrent::HashString* hash);
+
+  static const int create_start    = 0x1;
+  static const int create_tied     = 0x2;
+  static const int create_quiet    = 0x4;
+  static const int create_raw_data = 0x8;
+
+  typedef std::vector<std::string> command_list_type;
+
+  // Temporary, find a better place for this.
+  void                try_create_download(const std::string& uri, int flags, const command_list_type& commands);
+  void                try_create_download_expand(const std::string& uri, int flags, command_list_type commands = command_list_type());
+  void                try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile);
+
+private:
+  typedef RangeMap<uint32_t, torrent::ThrottlePair> AddressThrottleMap;
+
+  void                create_http(const std::string& uri);
+  void                create_final(std::istream* s);
+
+  void                initialize_bencode(Download* d);
+
+  void                receive_http_failed(std::string msg);
+  void                receive_hashing_changed();
+
+  DownloadList*       m_downloadList;
+  DownloadStore*      m_downloadStore;
+  FileStatusCache*    m_fileStatusCache;
+  HttpQueue*          m_httpQueue;
+  CurlStack*          m_httpStack;
+
+  View*               m_hashingView;
+
+  ThrottleMap         m_throttles;
+  AddressThrottleMap  m_addressThrottles;
+
+  Log                 m_logImportant;
+  Log                 m_logComplete;
+};
+
+// Meh, cleanup.
+extern void receive_tracker_dump(const std::string& url, const char* data, size_t size);
+
+}
+
+#endif

--- a/src/core/printable.h
+++ b/src/core/printable.h
@@ -0,0 +1,16 @@
+#ifndef PRINTABLE_H
+#define PRINTABLE_H
+
+#include <iostream>
+
+class Printable {
+	public:
+		virtual std::string to_string() const = 0;
+};
+
+template<typename _CharT,class _Traits> inline std::basic_ostream<_CharT,_Traits>&
+	operator<<( std::basic_ostream<_CharT,_Traits>& out, const Printable& val) {
+	return out << val.to_string();
+}
+
+#endif

--- a/src/core/regex_namespace.h
+++ b/src/core/regex_namespace.h
@@ -0,0 +1,6 @@
+#ifndef REGEXNAMESPACE_H
+#define REGEXNAMESPACE_H
+
+namespace regex = utils;
+
+#endif

--- a/src/utils/Makefile.am
+++ b/src/utils/Makefile.am
@@ -9,6 +9,8 @@
 	lockfile.cc \
 	lockfile.h \
 	socket_fd.cc \
-	socket_fd.h
+	socket_fd.h \
+	pattern.cc \
+	pattern.h
 
 INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)

--- a/src/utils/Makefile.in
+++ b/src/utils/Makefile.in
@@ -58,7 +58,7 @@
 libsub_utils_a_LIBADD =
 am_libsub_utils_a_OBJECTS = directory.$(OBJEXT) \
 	file_status_cache.$(OBJEXT) lockfile.$(OBJEXT) \
-	socket_fd.$(OBJEXT)
+	socket_fd.$(OBJEXT) pattern.$(OBJEXT)
 libsub_utils_a_OBJECTS = $(am_libsub_utils_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -224,7 +224,9 @@
 	lockfile.cc \
 	lockfile.h \
 	socket_fd.cc \
-	socket_fd.h
+	socket_fd.h \
+	pattern.cc \
+	pattern.h
 
 INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)
 all: all-am
@@ -279,6 +281,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_status_cache.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lockfile.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pattern.Po@am__quote@
 
 .cc.o:
 @am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<

--- a/src/utils/Makefile.in.orig
+++ b/src/utils/Makefile.in.orig
@@ -0,0 +1,510 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/utils
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/scripts/attributes.m4 \
+	$(top_srcdir)/scripts/checks.m4 \
+	$(top_srcdir)/scripts/common.m4 \
+	$(top_srcdir)/scripts/libtool.m4 \
+	$(top_srcdir)/scripts/ltoptions.m4 \
+	$(top_srcdir)/scripts/ltsugar.m4 \
+	$(top_srcdir)/scripts/ltversion.m4 \
+	$(top_srcdir)/scripts/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libsub_utils_a_AR = $(AR) $(ARFLAGS)
+libsub_utils_a_LIBADD =
+am_libsub_utils_a_OBJECTS = directory.$(OBJEXT) \
+	file_status_cache.$(OBJEXT) lockfile.$(OBJEXT) \
+	socket_fd.$(OBJEXT)
+libsub_utils_a_OBJECTS = $(am_libsub_utils_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libsub_utils_a_SOURCES)
+DIST_SOURCES = $(libsub_utils_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
+CPPUNIT_CONFIG = @CPPUNIT_CONFIG@
+CPPUNIT_LIBS = @CPPUNIT_LIBS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libcurl_CFLAGS = @libcurl_CFLAGS@
+libcurl_LIBS = @libcurl_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libtorrent_CFLAGS = @libtorrent_CFLAGS@
+libtorrent_LIBS = @libtorrent_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sigc_CFLAGS = @sigc_CFLAGS@
+sigc_LIBS = @sigc_LIBS@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = libsub_utils.a
+libsub_utils_a_SOURCES = \
+	directory.cc \
+	directory.h \
+	file_status_cache.cc \
+	file_status_cache.h \
+	list_focus.h \
+	lockfile.cc \
+	lockfile.h \
+	socket_fd.cc \
+	socket_fd.h
+
+INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/utils/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/utils/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libsub_utils.a: $(libsub_utils_a_OBJECTS) $(libsub_utils_a_DEPENDENCIES) 
+	-rm -f libsub_utils.a
+	$(libsub_utils_a_AR) libsub_utils.a $(libsub_utils_a_OBJECTS) $(libsub_utils_a_LIBADD)
+	$(RANLIB) libsub_utils.a
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/directory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_status_cache.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lockfile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Po@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

--- a/src/utils/pattern.cc
+++ b/src/utils/pattern.cc
@@ -0,0 +1,79 @@
+#include <string>
+#include <sys/types.h>
+#include <ctype.h>
+#include <regex.h>
+
+#include "pattern.h"
+
+namespace utils {
+
+int Pattern::countGroups( const std::string& str ) {
+	int count1 = 0;
+	int count2 = 0;
+
+	for( size_t index = -1; (index = str.find( '(', index+1 )) != std::string::npos;  )
+		count1++;
+	for( size_t index = -1; (index = str.find( ')', index+1 )) != std::string::npos;  )
+		count2++;
+
+	return (count1 < count2) ? count1 : count2;
+}
+
+Pattern::Pattern( const std::string& pattern, Flags flags ) :	lastResult(-1),
+								preg(NULL) {
+	int regFlags = REG_EXTENDED | REG_ICASE | REG_NEWLINE;
+	if( !(flags & CASE_SENSITIVE) )
+		regFlags ^= REG_ICASE;
+	if( (flags & DOT_MATCH_NEWLINE) )
+		regFlags ^= REG_NEWLINE;
+
+	preg = new regex_t;
+	numGroups = countGroups( pattern ) + 1;
+
+	lastResult = regcomp( preg, pattern.c_str(), regFlags );
+}
+
+Pattern::~Pattern() {
+	regfree( preg );
+	delete( preg );
+}
+
+std::string Pattern::getLastError() const {
+	char errBuf[1024];
+	regerror( lastResult, preg, errBuf, sizeof(errBuf) );
+	return std::string(errBuf);
+}
+
+Match Pattern::match( const std::string& expression ) const {
+
+	regmatch_t* pmatch = new regmatch_t[numGroups];
+	int res = regexec( preg, expression.c_str(), numGroups, pmatch, 0 );
+	return Match( expression, numGroups, pmatch, res, getLastError() );
+}
+
+Match::Match( const std::string& expr, int ngroups, regmatch_t* groups, int result, const std::string& message ) : 
+	expression( expr ), 
+	nmatch( ngroups ), 
+	pmatch( groups ),
+	matchResult( result ),
+	matchMessage( message ) {
+}
+
+std::string Match::group( int i ) {
+	if( (i >= nmatch) || (pmatch[i].rm_so < 0) )
+		return "";
+
+	return expression.substr( pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so );
+}
+
+std::string& trim( std::string& str ) {
+	std::string::iterator it;
+	for( it = str.begin(); (it < str.end()) && ( isspace(*it) || (*it == 0) ) ; it++ );
+	str.erase( str.begin(), it );
+  	for( it = str.end()-1; (it >= str.begin()) && ( isspace(*it) || (*it == 0) ) ; it-- );
+	str.erase( ++it, str.end() );
+	return str;
+}
+
+}
+

--- a/src/utils/pattern.h
+++ b/src/utils/pattern.h
@@ -0,0 +1,59 @@
+#ifndef PATTERN_H
+#define PATTERN_H
+
+#include <string>
+#include <sys/types.h>
+#include <ctype.h>
+#include <regex.h>
+
+namespace utils {
+
+class Match {
+	public:
+		Match( const std::string& expr, int ngroups, regmatch_t* pmatch, int matchResult, const std::string& matchMessage );
+		~Match() { delete[] pmatch; }
+		std::string group( int i );
+		bool found() { return (matchResult == 0); }
+		bool matches() { return found(); }
+		std::string& getMatchMessage() { return matchMessage; }
+
+	private:
+		std::string	expression;
+		int		nmatch;
+		regmatch_t*	pmatch;
+		int		matchResult;
+		std::string	matchMessage;
+};
+
+class Pattern {
+	public:
+		enum Flags {
+			DEFAULT = 0,		// REG_EXTENDED | REG_ICASE | REG_NEWLINE
+			CASE_SENSITIVE,
+			DOT_MATCH_NEWLINE
+		};
+
+	public:
+		Pattern( const std::string& pattern, Flags f = Pattern::DEFAULT );
+		~Pattern();
+		bool isSuccess() { return (lastResult == 0); }
+		std::string getLastError() const;
+		Match match( const std::string& expression ) const;
+
+	private:
+		int countGroups( const std::string& str );
+
+	private:
+		regex_t*	preg;
+		int		lastResult;
+		int		numGroups;
+};
+
+
+std::string& trim( std::string& str );
+
+}
+
+// end of ifdef PATTERN_H
+#endif
+

