1# -*- coding: utf-8 -*- 2# 3# Basic plugin template created by: 4# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> 5# 2007-2009 Andrew Resch <andrewresch@gmail.com> 6# 2009 Damien Churchill <damoxc@gmail.com> 7# 2010 Pedro Algarvio <pedro@algarvio.me> 8# 2017 Calum Lind <calumlind+deluge@gmail.com> 9# 10# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with 11# the additional special exception to link portions of this program with the OpenSSL library. 12# See LICENSE for more details. 13# 14 15from __future__ import unicode_literals 16 17import os.path 18from functools import wraps 19from sys import exc_info 20 21import six 22from pkg_resources import resource_filename 23 24 25def get_resource(filename): 26 return resource_filename(__package__, os.path.join('data', filename)) 27 28 29def raises_errors_as(error): 30 """Factory class that returns a decorator which wraps the decorated 31 function to raise all exceptions as the specified error type. 32 33 """ 34 35 def decorator(func): 36 """Returns a function which wraps the given func to raise all exceptions as error.""" 37 38 @wraps(func) 39 def wrapper(self, *args, **kwargs): 40 """Wraps the function in a try..except block and calls it with the specified args. 41 42 Raises: 43 Any exceptions as error preserving the message and traceback. 44 45 """ 46 try: 47 return func(self, *args, **kwargs) 48 except Exception: 49 (value, tb) = exc_info()[1:] 50 six.reraise(error, value, tb) 51 52 return wrapper 53 54 return decorator 55 56 57def remove_zeros(ip): 58 """Removes unneeded zeros from ip addresses. 59 60 Args: 61 ip (str): The ip address. 62 63 Returns: 64 str: The ip address without the unneeded zeros. 65 66 Example: 67 000.000.000.003 -> 0.0.0.3 68 69 """ 70 return '.'.join([part.lstrip('0').zfill(1) for part in ip.split('.')]) 71 72 73class BadIP(Exception): 74 _message = None 75 76 def __init__(self, message): 77 super(BadIP, self).__init__(message) 78 79 def __set_message(self, message): 80 self._message = message 81 82 def __get_message(self): 83 return self._message 84 85 message = property(__get_message, __set_message) 86 del __get_message, __set_message 87 88 89class IP(object): 90 __slots__ = ('q1', 'q2', 'q3', 'q4', '_long') 91 92 def __init__(self, q1, q2, q3, q4): 93 self.q1 = q1 94 self.q2 = q2 95 self.q3 = q3 96 self.q4 = q4 97 self._long = 0 98 for q in self.quadrants(): 99 self._long = (self._long << 8) | int(q) 100 101 @property 102 def address(self): 103 return '.'.join([str(q) for q in [self.q1, self.q2, self.q3, self.q4]]) 104 105 @property 106 def long(self): 107 return self._long 108 109 @classmethod 110 def parse(cls, ip): 111 try: 112 q1, q2, q3, q4 = [int(q) for q in ip.split('.')] 113 except ValueError: 114 raise BadIP(_('The IP address "%s" is badly formed' % ip)) 115 if q1 < 0 or q2 < 0 or q3 < 0 or q4 < 0: 116 raise BadIP(_('The IP address "%s" is badly formed' % ip)) 117 elif q1 > 255 or q2 > 255 or q3 > 255 or q4 > 255: 118 raise BadIP(_('The IP address "%s" is badly formed' % ip)) 119 return cls(q1, q2, q3, q4) 120 121 def quadrants(self): 122 return (self.q1, self.q2, self.q3, self.q4) 123 124 # def next_ip(self): 125 # (q1, q2, q3, q4) = self.quadrants() 126 # if q4 >= 255: 127 # if q3 >= 255: 128 # if q2 >= 255: 129 # if q1 >= 255: 130 # raise BadIP(_('There is not a next IP address')) 131 # q1 += 1 132 # else: 133 # q2 += 1 134 # else: 135 # q3 += 1 136 # else: 137 # q4 += 1 138 # return IP(q1, q2, q3, q4) 139 # 140 # def previous_ip(self): 141 # (q1, q2, q3, q4) = self.quadrants() 142 # if q4 <= 1: 143 # if q3 <= 1: 144 # if q2 <= 1: 145 # if q1 <= 1: 146 # raise BadIP(_('There is not a previous IP address')) 147 # q1 -= 1 148 # else: 149 # q2 -= 1 150 # else: 151 # q3 -= 1 152 # else: 153 # q4 -= 1 154 # return IP(q1, q2, q3, q4) 155 156 def __lt__(self, other): 157 if isinstance(other, ''.__class__): 158 other = IP.parse(other) 159 return self.long < other.long 160 161 def __gt__(self, other): 162 if isinstance(other, ''.__class__): 163 other = IP.parse(other) 164 return self.long > other.long 165 166 def __eq__(self, other): 167 if isinstance(other, ''.__class__): 168 other = IP.parse(other) 169 return self.long == other.long 170 171 def __repr__(self): 172 return '<%s long=%s address="%s">' % ( 173 self.__class__.__name__, 174 self.long, 175 self.address, 176 ) 177