- fix deps
[packages/rtorrent.git] / rtorrent-ip_filter.patch
1 diff -urN rtorrent-0.8.2.orig/ip_filter_test.cc rtorrent-0.8.2/ip_filter_test.cc
2 --- rtorrent-0.8.2.orig/ip_filter_test.cc       1970-01-01 01:00:00.000000000 +0100
3 +++ rtorrent-0.8.2/ip_filter_test.cc    2008-05-21 01:17:53.000000000 +0200
4 @@ -0,0 +1,104 @@
5 +#include <iostream>
6 +#include <fstream>
7 +#include <string>
8 +#include <map>
9 +
10 +#include "ip_address.h"
11 +#include "ip_range.h"
12 +#include "ip_filter.h"
13 +
14 +#define null NULL
15 +
16 +using namespace std;
17 +using namespace core;
18 +
19 +void testIncludes( map<const IpAddress,IpRange::ptr>& m, string s ) {
20 +        cout << "** test includes '" << s << "'" << endl;
21 +        const IpAddress* ip = IpAddress::parse( s );
22 +        if( !ip ) {
23 +                cout << "ip is invalid" << endl;
24 +                return;
25 +        }
26 +        for( map<const IpAddress,IpRange::ptr>::iterator it = m.begin() ; it != m.end(); it++ ) {
27 +                const IpAddress* a = &(it->first);
28 +                IpRange* ir = it->second;
29 +                cout << '\t' << ir->to_string() << ": " << (ir->includes( *ip ) ? "true" : "false") << endl;
30 +        }
31 +}
32 +
33 +void testMap( map<const IpAddress,IpRange::ptr>& m ) {
34 +        for( map<const IpAddress,IpRange::ptr>::iterator it = m.begin() ; it != m.end(); it++ ) {
35 +                const IpAddress a = it->first;
36 +                IpRange* ir = it->second;
37 +                cout << a << ": " << *ir << endl;
38 +        }
39 +}
40 +
41 +IpFilter* testLoad( char* fileName ) {
42 +        cout << "testLoad" << endl;
43 +        string s( fileName );
44 +        IpFilter* f = new IpFilter();
45 +
46 +        f->add_from_file( s );
47 +        cout << *f << endl;
48 +
49 +        return f;
50 +}
51 +
52 +IpFilter* testLoadMultiple( char* fileName[], int size ) {
53 +        cout << "testLoadMultiple" << endl;
54 +        IpFilter* f = new IpFilter();
55 +
56 +        int entries = 0;
57 +        for( int i = 0; i < size; i++ ) {
58 +                cout << "Loading '" << fileName[i] << "'...";
59 +               cout.flush();
60 +                int merges = f->add_from_file( fileName[i] );
61 +                if( merges < 0 )
62 +                        break;
63 +                cout << "done. loaded " << (f->size()-entries) << " entries, " << merges << " merges"  << endl;
64 +                entries = f->size();
65 +        }
66 +       cout << "Total loaded " << f->size() << " entries, " << f->get_merges() << " merges"  << endl;
67 +        //cerr << *f << endl;
68 +
69 +        return f;
70 +}
71 +
72 +void testIncludes( IpFilter* f, char* ip ) {
73 +        string s( ip );
74 +
75 +        cout << s << " filtered=" << (f->is_filtered(s) ? "true" : "false") << endl;
76 +}
77 +
78 +void testReload( IpFilter* f ) {
79 +       cout << "Reloading...";
80 +       cout.flush();
81 +       f->reload();
82 +       cout << "done. loaded " << f->size() << " entries, " << f->get_merges() << " merges"  << endl;
83 +}
84 +
85 +int main( int argn, char* argv[] ) {
86 +        try
87 +        {
88 +                cout << "testMain" << endl;
89 +                if( argn < 3 ) {
90 +                        cout << "aruments: file name, ip" << endl;
91 +                        return -1;
92 +                }
93 +
94 +                IpFilter* f = testLoadMultiple( &argv[1], argn-2 );
95 +               testReload( f );
96 +               testReload( f );
97 +//             testReload( f );
98 +                testIncludes( f, argv[argn-1] );
99 +                delete f;
100 +    }
101 +        catch (exception& e)
102 +        {
103 +                cout << e.what() << endl;
104 +        }
105 +
106 +        return 0;
107 +}
108 +
109 diff -urN rtorrent-0.8.2.orig/src/command_network.cc rtorrent-0.8.2/src/command_network.cc
110 --- rtorrent-0.8.2.orig/src/command_network.cc  2008-05-07 14:19:11.000000000 +0200
111 +++ rtorrent-0.8.2/src/command_network.cc       2008-09-11 08:39:12.000000000 +0200
112 @@ -36,6 +36,16 @@
113  
114  #include "config.h"
115  
116 +#include <string>
117 +#include <sstream>
118 +#include <list>
119 +#include <unistd.h>
120 +
121 +#include <string>
122 +#include <sstream>
123 +#include <list>
124 +#include <unistd.h>
125 +
126  #include <functional>
127  #include <rak/address_info.h>
128  #include <rak/path.h>
129 @@ -61,6 +71,14 @@
130  #include "control.h"
131  #include "command_helpers.h"
132  
133 +#include <boost/algorithm/string/trim.hpp>
134 +#include "core/ip_filter.h"
135 +
136 +
137 +#include <boost/algorithm/string/trim.hpp>
138 +#include "core/ip_filter.h"
139 +
140 +
141  torrent::Object
142  apply_encryption(const torrent::Object& rawArgs) {
143    const torrent::Object::list_type& args = rawArgs.as_list();
144 @@ -94,6 +112,57 @@
145  }
146  
147  torrent::Object
148 +apply_ip_filter(const torrent::Object& rawArgs) {
149 +  const torrent::Object::list_type& args = rawArgs.as_list();
150 +
151 +  std::list<std::string> files;
152 +
153 +  for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
154 +    std::string file( itr->as_string() );
155 +    boost::trim( file );
156 +    if( access(file.c_str(),F_OK | R_OK) ) 
157 +      throw torrent::input_error("IpFilter file '" + file + "' does not exist or not readable. Filter could not be loaded");
158 +    files.push_back( file );
159 +  }
160 +
161 +  std::stringstream logMsg; 
162 +  if( files.empty() ) {
163 +    logMsg << "IpFilter is empty";
164 +    control->core()->push_log( logMsg.str().c_str() );
165 +  }
166 +  else {
167 +    core::IpFilter* f = new core::IpFilter();
168 +    logMsg << "IpFilter is initialized with files: ";
169 +    int entries = 0;
170 +    for( std::list<std::string>::iterator itr = files.begin(); itr != files.end(); itr++) {
171 +      std::cout << "Loading IP filters from '" << *itr << "'...";
172 +      std::cout.flush();
173 +      if( itr != files.begin() )
174 +        logMsg << ", ";
175 +      logMsg << *itr;
176 +      int merges = f->add_from_file( *itr );
177 +      if( merges < 0 ) {
178 +        std::cout << "error" << std::endl;
179 +        std::cout.flush();
180 +        throw torrent::input_error("IpFilter could not load file '" + *itr + "'");
181 +      }
182 +      std::cout << "done. Loaded " << (f->size()-entries) << " ranges. " << merges << " ranges were merged." << std::endl;
183 +      std::cout.flush();
184 +      entries = f->size();
185 +    }
186 +    control->core()->push_log( logMsg.str().c_str() );
187 +    std::stringstream logMsg2("IpFilter loaded with "); 
188 +    logMsg2 << f->size() << " ranges total. " << f->get_merges() << " ranges were merged.";
189 +    control->core()->push_log( logMsg2.str().c_str() );
190 +    std::cout << logMsg2 << std::endl;
191 +    std::cout.flush();
192 +    control->core()->set_ip_filter( f );
193 +  }
194 +
195 +  return torrent::Object();
196 +}
197 +
198 +torrent::Object
199  apply_tos(const torrent::Object& rawArg) {
200    rpc::Command::value_type value;
201    torrent::ConnectionManager* cm = torrent::connection_manager();
202 @@ -366,6 +486,12 @@
203  
204    ADD_VARIABLE_BOOL("peer_exchange", true);
205  
206 +  ADD_COMMAND_VOID("reload_ip_filter",           rak::make_mem_fun(control->core(), &core::Manager::reload_ip_filter));
207 +  ADD_COMMAND_LIST("ip_filter",          rak::ptr_fn(&apply_ip_filter));
208 +
209 +  ADD_COMMAND_VOID("reload_ip_filter",           rak::make_mem_fun(control->core(), &core::Manager::reload_ip_filter));
210 +  ADD_COMMAND_LIST("ip_filter",          rak::ptr_fn(&apply_ip_filter));
211 +
212    // Not really network stuff:
213    ADD_VARIABLE_BOOL("handshake_log", false);
214    ADD_VARIABLE_STRING("tracker_dump", "");
215 diff -urN rtorrent-0.8.2.orig/src/core/ip_address.cc rtorrent-0.8.2/src/core/ip_address.cc
216 --- rtorrent-0.8.2.orig/src/core/ip_address.cc  1970-01-01 01:00:00.000000000 +0100
217 +++ rtorrent-0.8.2/src/core/ip_address.cc       2008-05-21 01:15:13.000000000 +0200
218 @@ -0,0 +1,25 @@
219 +#include <cstdlib>
220 +#include <string>
221 +#include <arpa/inet.h>
222 +#include <boost/xpressive/xpressive.hpp>
223 +
224 +#include "ip_address.h"
225 +
226 +namespace core {
227 +
228 +std::pair<bool,uint32_t> IpAddress::to_int( const std::string& address ) {
229 +       uint32_t a;
230 +       int r = inet_pton( AF_INET, address.c_str(), &a);
231 +       if( r )
232 +               a = ntohl( a );
233 +        return std::pair<bool,uint32_t>( (r!=0), a );
234 +}
235 +
236 +std::string IpAddress::to_string() const {
237 +       char buf[128] = "";
238 +       uint32_t a = htonl( m_address );
239 +       inet_ntop( AF_INET, &a, buf, sizeof(buf) );
240 +        return std::string( buf );
241 +}
242 +
243 +}
244 diff -urN rtorrent-0.8.2.orig/src/core/ip_address.h rtorrent-0.8.2/src/core/ip_address.h
245 --- rtorrent-0.8.2.orig/src/core/ip_address.h   1970-01-01 01:00:00.000000000 +0100
246 +++ rtorrent-0.8.2/src/core/ip_address.h        2008-05-21 01:15:13.000000000 +0200
247 @@ -0,0 +1,67 @@
248 +#ifndef IPADDRESS_H
249 +#define IPADDRESS_H
250 +
251 +#include <string>
252 +#include <boost/xpressive/xpressive.hpp>
253 +
254 +#include "printable.h"
255 +#include "regex_namespace.h"
256 +
257 +namespace core {
258 +
259 +class IpAddress : public Printable {
260 +        friend class IpRange;
261 +
262 +        private: // constants
263 +                static const std::string        PATTERN_IP_EXPRESSION;
264 +                static const std::string        PATTERN_IP_BYTES_EXPRESSION;
265 +                static const regex::sregex      PATTERN_IP_BYTES;
266 +
267 +                static const int                        GRP_IP_FIRST_BYTE;
268 +                static const int                        GRP_IP_BYTES_COUNT;
269 +
270 +        private: // fields
271 +                uint32_t                     m_address;
272 +
273 +        private: // static methods
274 +
275 +        private: // dynamic methods
276 +                IpAddress() : m_address(0) {}
277 +
278 +                void copy( const IpAddress& addr ) {
279 +                        m_address = addr.m_address;
280 +                }
281 +
282 +        public: // static methods
283 +                static std::pair<bool,uint32_t> to_int( const std::string& strAddress );
284 +                static IpAddress* parse( const std::string& strAddress ) {
285 +                                       std::pair<bool,uint32_t> result = to_int( strAddress );
286 +                                       return ( !result.first ) ? NULL : new IpAddress( result.second );
287 +                               }
288 +
289 +        public: // dynamic methods
290 +                IpAddress( uint32_t address ) : m_address(address) {}
291 +                IpAddress( const IpAddress& addr ) { copy( addr ); }
292 +                IpAddress& operator= ( const IpAddress& addr ) { copy( addr ); return *this; } 
293 +
294 +                operator uint32_t() const { return m_address; }
295 +
296 +                bool operator>= ( const IpAddress& ip ) const { return (m_address >=    ip.m_address); }
297 +                bool operator<= ( const IpAddress& ip ) const { return (m_address <=    ip.m_address); }
298 +                bool operator<  ( const IpAddress& ip ) const { return (m_address <     ip.m_address); }
299 +                bool operator>  ( const IpAddress& ip ) const { return (m_address >     ip.m_address); }
300 +                bool operator== ( const IpAddress& ip ) const { return (m_address ==    ip.m_address); }
301 +                bool operator!= ( const IpAddress& ip ) const { return (m_address !=    ip.m_address); }
302 +
303 +                bool operator>= ( uint32_t ip ) const { return (m_address >= ip); }
304 +                bool operator<= ( uint32_t ip ) const { return (m_address <= ip); }
305 +                bool operator<  ( uint32_t ip ) const { return (m_address <  ip); }
306 +                bool operator>  ( uint32_t ip ) const { return (m_address >  ip); }
307 +                bool operator== ( uint32_t ip ) const { return (m_address == ip); }
308 +                bool operator!= ( uint32_t ip ) const { return (m_address != ip); }
309 +
310 +                std::string to_string() const;
311 +};
312 +
313 +}
314 +#endif
315 diff -urN rtorrent-0.8.2.orig/src/core/ip_filter.cc rtorrent-0.8.2/src/core/ip_filter.cc
316 --- rtorrent-0.8.2.orig/src/core/ip_filter.cc   1970-01-01 01:00:00.000000000 +0100
317 +++ rtorrent-0.8.2/src/core/ip_filter.cc        2008-05-21 01:15:13.000000000 +0200
318 @@ -0,0 +1,166 @@
319 +#include <string>
320 +#include <map>
321 +#include <list>
322 +#include <fstream>
323 +#include <boost/algorithm/string/trim.hpp>
324 +
325 +#include "ip_filter.h"
326 +
327 +namespace core {
328 +
329 +int IpFilter::merge_and_insert( range_map* rs, IpRange* r ) {
330 +        if( !r || !r->get_from() )
331 +                return 0;
332 +
333 +        std::pair<const IpAddress,IpRange::ptr> p( *r->get_from(), IpRange::ptr(r) );
334 +        std::pair<range_itr,bool> duo = rs->insert( p );
335 +
336 +        range_itr idx = duo.first;
337 +        bool wasInserted = duo.second;
338 +        IpRange* curr = NULL;
339 +        int mergeCount = 0;
340 +
341 +        if( !wasInserted ) { // exactly the same start address already exists
342 +                curr = idx->second;
343 +                if( *curr->get_to() < *r->get_to() )
344 +                        curr->set_to( r->get_to() );
345 +               delete r;
346 +               r = curr;
347 +               mergeCount++;
348 +        }
349 +        else {
350 +                if( idx != rs->begin() ) {
351 +                        --idx;
352 +                        curr = idx->second; // previous
353 +                        if( *r->get_from() <= *curr->get_to() )
354 +                                r = curr;
355 +                        else
356 +                                ++idx;
357 +                }
358 +        }
359 +
360 +        if( idx != rs->end() )
361 +                ++idx;
362 +
363 +        while( idx != rs->end() ) {
364 +                curr = idx->second;
365 +                if( *r->get_to() < *curr->get_from() )
366 +                        break;
367 +
368 +                std::string d = r->get_description();
369 +                d += " / " + curr->get_description();
370 +                r->set_description( d );
371 +                if( *r->get_to() < *curr->get_to() )
372 +                        r->set_to( curr->get_to() );
373 +                rs->erase( idx++ );
374 +                delete curr;
375 +                mergeCount++;
376 +        }
377 +        return mergeCount;
378 +}
379 +
380 +int IpFilter::add_from_file( const std::string& fileName, range_map* rs, str_list* files ) {
381 +        std::ifstream in( fileName.c_str() );
382 +        std::string line;
383 +        int mergeCount = 0;
384 +
385 +        if( in.fail() || !in.is_open() )
386 +          return -1;
387 +
388 +        while( in.good() ) {
389 +                std::getline( in, line );
390 +                boost::trim( line );
391 +
392 +                if( (line[0] == '#') || (line.length() == 0) )
393 +                        continue;
394 +
395 +                IpRange* ir = IpRange::parse( line );
396 +                if( !ir || !ir->get_from() || !ir->get_to() )
397 +                        continue;
398 +
399 +                mergeCount += merge_and_insert( rs, ir );
400 +        }
401 +        files->push_back( std::string(fileName) );
402 +        in.close();
403 +
404 +        m_merges += mergeCount;
405 +        return mergeCount;
406 +}
407 +
408 +int IpFilter::add_from_file( const std::string& fileName ) {
409 +        if( !m_ranges )
410 +                m_ranges = new range_map();
411 +        if( !m_loadedFiles )
412 +                m_loadedFiles = new std::list<std::string>();
413 +
414 +        return add_from_file( fileName, m_ranges, m_loadedFiles );
415 +}
416 +
417 +int IpFilter::reload() {
418 +        if( !m_loadedFiles || m_loadedFiles->empty() )
419 +                return 0;
420 +
421 +        range_map* rs = new range_map();
422 +        str_list* files = new str_list();
423 +        int mergeCount = 0;
424 +        for( str_list::const_iterator it = m_loadedFiles->begin(), end = m_loadedFiles->end(); it != end; it++ )
425 +                mergeCount += add_from_file( *it, rs, files );
426 +
427 +        range_map* rsOld = m_ranges;
428 +        m_ranges = rs;
429 +        if( rsOld ) {
430 +                clear( rsOld );
431 +                delete rsOld;
432 +        }
433 +
434 +        str_list* filesOld = m_loadedFiles;
435 +        m_loadedFiles = files;
436 +        if( filesOld ) {
437 +                clear( filesOld );
438 +                delete filesOld;
439 +        }
440 +
441 +       m_merges = mergeCount;
442 +        return mergeCount;
443 +}
444 +
445 +IpRange* IpFilter::find_range( int ip ) const {
446 +        if( (ip >= 0) && m_ranges && !m_ranges->empty() ) {
447 +                range_itr idx = m_ranges->lower_bound( ip );
448 +                if( idx != m_ranges->begin() )
449 +                        --idx;
450 +                IpRange* curr = idx->second;
451 +                if( curr->includes( ip ) )
452 +                        return curr;
453 +        }
454 +        return NULL;
455 +}
456 +
457 +std::string IpFilter::to_string() const {
458 +        std::stringstream result;
459 +        if( !m_ranges )
460 +                result << "NULL" << std::endl;
461 +        else {
462 +                for( range_map::const_iterator it = m_ranges->begin() ; it != m_ranges->end(); it++ ) {
463 +                        const IpAddress a = it->first;
464 +                        IpRange* ir = it->second;
465 +                        result << a << ": " << *ir << std::endl;
466 +                }
467 +        }
468 +        return result.str();
469 +}
470 +
471 +void IpFilter::clear( range_map* map ) {
472 +       if( map ) {
473 +               for( range_itr i = map->begin(), j = map->end(); i != j; i++ )
474 +                       delete i->second;
475 +               map->clear();
476 +       }
477 +}
478 +
479 +void IpFilter::clear( str_list* list ) {
480 +       if( list )
481 +               list->clear();
482 +}
483 +
484 +}
485 diff -urN rtorrent-0.8.2.orig/src/core/ip_filter.h rtorrent-0.8.2/src/core/ip_filter.h
486 --- rtorrent-0.8.2.orig/src/core/ip_filter.h    1970-01-01 01:00:00.000000000 +0100
487 +++ rtorrent-0.8.2/src/core/ip_filter.h 2008-05-21 01:15:13.000000000 +0200
488 @@ -0,0 +1,86 @@
489 +#ifndef IPFILTER_H
490 +#define IPFILTER_H
491 +
492 +#include <string>
493 +#include <map>
494 +#include <list>
495 +
496 +#include "printable.h"
497 +#include "ip_address.h"
498 +#include "ip_range.h"
499 +#include "regex_namespace.h"
500 +
501 +namespace core {
502 +
503 +typedef std::map<const IpAddress,IpRange::ptr>  range_map;
504 +typedef range_map::iterator                     range_itr;
505 +typedef std::list<std::string>                  str_list;
506 +
507 +class IpFilter : public Printable {
508 +        private: // fields
509 +                int m_merges;
510 +                range_map* m_ranges;
511 +                str_list* m_loadedFiles;
512 +
513 +        private: // static methods
514 +                static void clear( range_map* map );
515 +                static void clear( str_list* list );
516 +
517 +        private: // dynamic methods
518 +                void init_members(void) { // to avoid long constructor lines for every ctor
519 +                  m_ranges = NULL;
520 +                  m_loadedFiles = NULL;
521 +                  m_merges = 0;
522 +                }
523 +                int merge_and_insert( range_map* rs, IpRange* r );
524 +                int add_from_file( const std::string& fileName, range_map* rs, str_list* files );
525 +
526 +        public: // static methods
527 +
528 +        public: // dynamic methods
529 +                IpFilter() { init_members(); }
530 +                ~IpFilter() {
531 +                        clear();
532 +                        if( m_ranges ) delete m_ranges;
533 +                        if( m_loadedFiles ) delete m_loadedFiles;
534 +                        m_ranges = NULL;
535 +                        m_loadedFiles = NULL;
536 +                }
537 +                IpFilter( std::string* files, int size ) {
538 +                        init_members();
539 +                        for( int i = 0; i < size; i++, files++ )
540 +                                add_from_file( *files );
541 +                }
542 +                IpFilter( str_list& files ) {
543 +                        init_members();
544 +                        for( str_list::const_iterator i = files.begin(), last = files.end(); i != last; i++ )
545 +                                add_from_file( *i );
546 +                }
547 +                IpFilter( IpFilter& f ) {
548 +                        init_members();
549 +                        m_ranges = new range_map( *f.m_ranges );
550 +                        m_loadedFiles = new str_list( *f.m_loadedFiles );
551 +                }
552 +
553 +                int reload();
554 +                int add_from_file( const std::string& fileName );
555 +                int add_from_file( char* fileName ) { std::string s( fileName ); return add_from_file(s); }
556 +                void clear() { clear( m_ranges ); clear( m_loadedFiles ); }
557 +
558 +                IpRange* find_range( int ip ) const;
559 +
560 +                bool is_filtered( int ip ) const { return (find_range( ip ) != NULL); }
561 +                bool is_filtered( std::string ip ) const { 
562 +                       static std::pair<bool,int> ipInt = IpAddress::to_int( ip );
563 +                       return (!ipInt.first ? false : is_filtered( ipInt.second )); 
564 +                }
565 +
566 +                std::string to_string() const;
567 +
568 +                int size(void) { return ( m_ranges ? m_ranges->size() : 0 ); }
569 +                int get_merges(void) { return m_merges; }
570 +                void set_files( str_list& files) { m_loadedFiles = new str_list( files ); }
571 +};
572 +
573 +}
574 +#endif
575 diff -urN rtorrent-0.8.2.orig/src/core/ip_filter_statics.cc rtorrent-0.8.2/src/core/ip_filter_statics.cc
576 --- rtorrent-0.8.2.orig/src/core/ip_filter_statics.cc   1970-01-01 01:00:00.000000000 +0100
577 +++ rtorrent-0.8.2/src/core/ip_filter_statics.cc        2008-05-21 01:15:35.000000000 +0200
578 @@ -0,0 +1,20 @@
579 +#include "ip_address.h"
580 +#include "ip_range.h"
581 +
582 +namespace core {
583 +
584 +const std::string       IpAddress::PATTERN_IP_EXPRESSION        = "((?:\\d{1,3}\\.){3}\\d{1,3})";
585 +const std::string       IpAddress::PATTERN_IP_BYTES_EXPRESSION  = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})";
586 +const regex::sregex     IpAddress::PATTERN_IP_BYTES             = regex::sregex::compile( PATTERN_IP_BYTES_EXPRESSION );
587 +
588 +const int               IpAddress::GRP_IP_FIRST_BYTE    = 1;
589 +const int               IpAddress::GRP_IP_BYTES_COUNT   = 4;
590 +
591 +const std::string       IpRange::PATTERN_RANGE_EXPRESSION       = "\\s*(.*)\\s*:\\s*" + IpAddress::PATTERN_IP_EXPRESSION + "\\s*-\\s*" + IpAddress::PATTERN_IP_EXPRESSION + "\\s*";
592 +const regex::sregex     IpRange::PATTERN_RANGE                  = regex::sregex::compile( PATTERN_RANGE_EXPRESSION );
593 +
594 +const int               IpRange::GRP_DESCRIPTION        = 1;
595 +const int               IpRange::GRP_FIRST_IP           = 2;
596 +const int               IpRange::GRP_SECOND_IP          = 3;
597 +
598 +}
599 diff -urN rtorrent-0.8.2.orig/src/core/ip_range.cc rtorrent-0.8.2/src/core/ip_range.cc
600 --- rtorrent-0.8.2.orig/src/core/ip_range.cc    1970-01-01 01:00:00.000000000 +0100
601 +++ rtorrent-0.8.2/src/core/ip_range.cc 2008-05-21 01:15:13.000000000 +0200
602 @@ -0,0 +1,41 @@
603 +#include <string>
604 +#include <boost/xpressive/xpressive.hpp>
605 +
606 +#include "ip_range.h"
607 +
608 +namespace core {
609 +
610 +IpRange* IpRange::parse( const std::string& s ) {
611 +        regex::smatch what;
612 +
613 +        if( !regex::regex_match( s, what, PATTERN_RANGE ) )
614 +                return NULL;
615 +
616 +        std::string     description     = what[ GRP_DESCRIPTION ].str();
617 +        std::string     ip1             = what[ GRP_FIRST_IP ].str();
618 +        std::string     ip2             = what[ GRP_SECOND_IP ].str();
619 +        IpAddress*      from            = IpAddress::parse( ip1 );
620 +if( !from ) std::cout << "!! from is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl;
621 +        IpAddress*      to              = IpAddress::parse( ip2 );
622 +if( !to ) std::cout << "!! to is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl;
623 +if( to && from && (*to < *from) ) std::cout << "!! to < from" << std::endl;
624 +
625 +        if( !from || !to || (*to < *from) )
626 +                return NULL;
627 +
628 +        IpRange* r = new IpRange();
629 +
630 +        r->m_description        = description;
631 +        r->m_from               = from;
632 +        r->m_to                 = to;
633 +
634 +        return r;
635 +}
636 +
637 +std::string IpRange::to_string() const {
638 +        std::stringstream result;
639 +        result << m_description << ": [" << m_from->to_string() << " - " << m_to->to_string() << ']';
640 +        return result.str();
641 +}
642 +
643 +}
644 diff -urN rtorrent-0.8.2.orig/src/core/ip_range.h rtorrent-0.8.2/src/core/ip_range.h
645 --- rtorrent-0.8.2.orig/src/core/ip_range.h     1970-01-01 01:00:00.000000000 +0100
646 +++ rtorrent-0.8.2/src/core/ip_range.h  2008-05-21 01:15:13.000000000 +0200
647 @@ -0,0 +1,67 @@
648 +#ifndef IPRANGE_H
649 +#define IPRANGE_H
650 +
651 +#include <string>
652 +#include <boost/xpressive/xpressive.hpp>
653 +#include <boost/shared_ptr.hpp>
654 +
655 +#include "printable.h"
656 +#include "ip_address.h"
657 +#include "regex_namespace.h"
658 +
659 +namespace core {
660 +
661 +class IpRange : public Printable {
662 +        private: // constants
663 +                static const std::string        PATTERN_RANGE_EXPRESSION;
664 +                static const regex::sregex      PATTERN_RANGE;
665 +
666 +                static const int                GRP_DESCRIPTION;
667 +                static const int                GRP_FIRST_IP;
668 +                static const int                GRP_SECOND_IP;
669 +
670 +        private: // fields
671 +                std::string             m_description;
672 +                const IpAddress*        m_from;
673 +                const IpAddress*        m_to;
674 +
675 +        private: // dynamic methods
676 +                IpRange() : m_description(), m_from(NULL), m_to(NULL) {}
677 +
678 +        public: // static methods
679 +                typedef IpRange* ptr;
680 +                static IpRange* parse( const std::string& s );
681 +
682 +        public: // dynamic methods
683 +                IpRange( IpRange& rng ) { copy(rng); }
684 +                IpRange& operator= ( IpRange& rng ) { copy(rng); return *this; }
685 +
686 +                void copy( IpRange& rng ) {
687 +                        m_description = rng.m_description;
688 +                        m_from = (!rng.m_from) ? NULL : new IpAddress( *rng.m_from );
689 +                        m_to = (!rng.m_to) ? NULL : new IpAddress( *rng.m_to );
690 +                }
691 +
692 +                const std::string&      get_description ( void ) const  { return m_description; }
693 +                const IpAddress*        get_from        ( void ) const  { return m_from; }
694 +                const IpAddress*        get_to          ( void ) const  { return m_to; }
695 +
696 +                void    set_description ( const std::string&    description )   { m_description = description; }
697 +                void    set_from        ( const IpAddress*      from )          { if( m_from ) delete m_from; m_from = new IpAddress( *from ); }
698 +                void    set_to          ( const IpAddress*      to )            { if( m_to ) delete m_to; m_to = new IpAddress( *to ); }
699 +
700 +                bool    includes( const IpAddress& ip ) const { return includes((uint32_t)ip); }
701 +                bool    includes( uint32_t ip ) const { return (*m_from <= ip) && (*m_to >= ip); }
702 +
703 +                ~IpRange() {
704 +                        delete m_from;
705 +                        m_from = NULL;
706 +                        delete m_to;
707 +                        m_to = NULL;
708 +                }
709 +
710 +                std::string to_string() const;
711 +};
712 +
713 +}
714 +#endif
715 diff -urN rtorrent-0.8.2.orig/src/core/manager.cc rtorrent-0.8.2/src/core/manager.cc
716 --- rtorrent-0.8.2.orig/src/core/manager.cc     2008-09-11 08:39:42.000000000 +0200
717 +++ rtorrent-0.8.2/src/core/manager.cc  2008-09-11 08:37:37.000000000 +0200
718 @@ -150,6 +150,24 @@
719    }
720  }
721  
722 +uint32_t
723 +Manager::filter_ip(const sockaddr* sa) {
724 +  IpRange* r = NULL;
725 +  // if something's wrong with filter or address it's gonna be allowed
726 +  if( m_ipFilter && sa ) {
727 +    const rak::socket_address* socketAddress = rak::socket_address::cast_from(sa);
728 +    if( socketAddress->is_valid() && (socketAddress->family() == rak::socket_address::af_inet) )
729 +      r = m_ipFilter->find_range( socketAddress->sa_inet()->address_h() );
730 +    if( r )
731 +      m_logComplete.push_front("Address '" + socketAddress->address_str() + "' is rejected by IP filter range '" + r->to_string());
732 +    else
733 +    if( rpc::call_command_value("get_handshake_log") )
734 +      m_logComplete.push_front("IP Filter allowed connection with '" + socketAddress->address_str() + "'");
735 +  }
736 +  return (r==NULL);
737 +}
738 +
739 +
740  void
741  Manager::push_log(const char* msg) {
742    m_logImportant.push_front(msg);
743 @@ -173,6 +191,8 @@
744    delete m_downloadStore;
745    delete m_httpQueue;
746    delete m_fileStatusCache;
747 +
748 +  set_ip_filter( NULL );
749  }
750  
751  void
752 @@ -216,6 +236,7 @@
753    m_downloadList->slot_map_erase()["9_delete_tied"]   = "d.delete_tied=";
754  
755    torrent::connection_manager()->set_signal_handshake_log(sigc::mem_fun(this, &Manager::handshake_log));
756 +  torrent::connection_manager()->set_filter(sigc::mem_fun(this, &Manager::filter_ip));
757  }
758  
759  void
760 @@ -548,4 +569,13 @@
761    }
762  }
763  
764 +void Manager::reload_ip_filter(void) {
765 +  if( m_ipFilter ) {
766 +    push_log("Reloading IP filter");
767 +    m_ipFilter->reload();
768 +    std::stringstream logMsg("IpFilter reloaded with "); 
769 +    logMsg << m_ipFilter->size() << " ranges total. " << m_ipFilter->get_merges() << " ranges were merged.";
770 +    push_log( logMsg.str().c_str() );
771 +  }
772 +}
773  }
774 diff -urN rtorrent-0.8.2.orig/src/core/manager.h rtorrent-0.8.2/src/core/manager.h
775 --- rtorrent-0.8.2.orig/src/core/manager.h      2008-05-07 14:19:11.000000000 +0200
776 +++ rtorrent-0.8.2/src/core/manager.h   2008-09-11 08:37:37.000000000 +0200
777 @@ -44,6 +44,8 @@
778  #include "poll_manager.h"
779  #include "log.h"
780  
781 +#include "ip_filter.h"
782 +
783  namespace torrent {
784    class Bencode;
785  }
786 @@ -107,6 +109,15 @@
787  
788    void                handshake_log(const sockaddr* sa, int msg, int err, const torrent::HashString* hash);
789  
790 +  uint32_t            filter_ip(const sockaddr* sa);
791 +
792 +  void                set_ip_filter( IpFilter* ipFilter ) {
793 +                        IpFilter* old = m_ipFilter;
794 +                        m_ipFilter = ipFilter;
795 +                        if( old ) delete old;
796 +                      }
797 +  void                reload_ip_filter(void);
798 +
799    static const int create_start    = 0x1;
800    static const int create_tied     = 0x2;
801    static const int create_quiet    = 0x4;
802 @@ -137,6 +148,8 @@
803    PollManager*        m_pollManager;
804    Log                 m_logImportant;
805    Log                 m_logComplete;
806 +
807 +  IpFilter*           m_ipFilter;
808  };
809  
810  // Meh, cleanup.
811 diff -urN rtorrent-0.8.2.orig/src/core/printable.h rtorrent-0.8.2/src/core/printable.h
812 --- rtorrent-0.8.2.orig/src/core/printable.h    1970-01-01 01:00:00.000000000 +0100
813 +++ rtorrent-0.8.2/src/core/printable.h 2008-05-21 01:15:51.000000000 +0200
814 @@ -0,0 +1,16 @@
815 +#ifndef PRINTABLE_H
816 +#define PRINTABLE_H
817 +
818 +#include <iostream>
819 +
820 +class Printable {
821 +        public:
822 +                virtual std::string to_string() const = 0;
823 +};
824 +
825 +template<typename _CharT,class _Traits> inline std::basic_ostream<_CharT,_Traits>&
826 +        operator<<( std::basic_ostream<_CharT,_Traits>& out, const Printable& val) {
827 +        return out << val.to_string();
828 +}
829 +
830 +#endif
831 diff -urN rtorrent-0.8.2.orig/src/core/regex_namespace.h rtorrent-0.8.2/src/core/regex_namespace.h
832 --- rtorrent-0.8.2.orig/src/core/regex_namespace.h      1970-01-01 01:00:00.000000000 +0100
833 +++ rtorrent-0.8.2/src/core/regex_namespace.h   2008-05-21 01:15:42.000000000 +0200
834 @@ -0,0 +1,6 @@
835 +#ifndef REGEXNAMESPACE_H
836 +#define REGEXNAMESPACE_H
837 +
838 +namespace regex = boost::xpressive;
839 +
840 +#endif
841 --- rtorrent-0.8.2.orig/src/core/Makefile.am    2008-05-07 08:19:11.000000000 -0400
842 +++ rtorrent-0.8.2/src/core/Makefile.am 2008-05-17 16:59:20.849853381 -0400
843 @@ -35,6 +35,15 @@
844         view.cc \
845         view.h \
846         view_manager.cc \
847 -       view_manager.h
848 +       view_manager.h \
849 +       ip_address.cc \
850 +       ip_address.h \
851 +       ip_filter.cc \
852 +       ip_filter.h \
853 +       ip_range.cc \
854 +       ip_range.h \
855 +       printable.h \
856 +       regex_namespace.h \
857 +       ip_filter_statics.cc
858  
859  INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)