]>
Commit | Line | Data |
---|---|---|
f22ab085 MT |
1 | #!/usr/bin/python |
2 | ||
3 | # Import all possible exception types. | |
4 | from .errors import * | |
5 | ||
6 | class DDNSProvider(object): | |
7 | INFO = { | |
8 | # A short string that uniquely identifies | |
9 | # this provider. | |
10 | "handle" : None, | |
11 | ||
12 | # The full name of the provider. | |
13 | "name" : None, | |
14 | ||
15 | # A weburl to the homepage of the provider. | |
16 | # (Where to register a new account?) | |
17 | "website" : None, | |
18 | ||
19 | # A list of supported protocols. | |
20 | "protocols" : ["ipv6", "ipv4"], | |
21 | } | |
22 | ||
23 | DEFAULT_SETTINGS = {} | |
24 | ||
25 | def __init__(self, core, **settings): | |
26 | self.core = core | |
27 | ||
28 | # Copy a set of default settings and | |
29 | # update them by those from the configuration file. | |
30 | self.settings = self.DEFAULT_SETTINGS.copy() | |
31 | self.settings.update(settings) | |
32 | ||
33 | def __repr__(self): | |
34 | return "<DDNS Provider %s (%s)>" % (self.name, self.handle) | |
35 | ||
36 | def __cmp__(self, other): | |
37 | return cmp(self.hostname, other.hostname) | |
38 | ||
39 | @property | |
40 | def name(self): | |
41 | """ | |
42 | Returns the name of the provider. | |
43 | """ | |
44 | return self.INFO.get("name") | |
45 | ||
46 | @property | |
47 | def website(self): | |
48 | """ | |
49 | Returns the website URL of the provider | |
50 | or None if that is not available. | |
51 | """ | |
52 | return self.INFO.get("website", None) | |
53 | ||
54 | @property | |
55 | def handle(self): | |
56 | """ | |
57 | Returns the handle of this provider. | |
58 | """ | |
59 | return self.INFO.get("handle") | |
60 | ||
61 | def get(self, key, default=None): | |
62 | """ | |
63 | Get a setting from the settings dictionary. | |
64 | """ | |
65 | return self.settings.get(key, default) | |
66 | ||
67 | @property | |
68 | def hostname(self): | |
69 | """ | |
70 | Fast access to the hostname. | |
71 | """ | |
72 | return self.get("hostname") | |
73 | ||
74 | @property | |
75 | def username(self): | |
76 | """ | |
77 | Fast access to the username. | |
78 | """ | |
79 | return self.get("username") | |
80 | ||
81 | @property | |
82 | def password(self): | |
83 | """ | |
84 | Fast access to the password. | |
85 | """ | |
86 | return self.get("password") | |
87 | ||
88 | def __call__(self): | |
89 | raise NotImplementedError | |
90 | ||
91 | def send_request(self, *args, **kwargs): | |
92 | """ | |
93 | Proxy connection to the send request | |
94 | method. | |
95 | """ | |
96 | return self.core.system.send_request(*args, **kwargs) | |
97 | ||
98 | def get_address(self, proto): | |
99 | """ | |
100 | Proxy method to get the current IP address. | |
101 | """ | |
102 | return self.core.system.get_address(proto) | |
103 | ||
104 | ||
105 | class DDNSProviderNOIP(DDNSProvider): | |
106 | INFO = { | |
107 | "handle" : "no-ip.com", | |
108 | "name" : "No-IP", | |
109 | "website" : "http://www.no-ip.com/", | |
110 | "protocols" : ["ipv4",] | |
111 | } | |
112 | ||
113 | # Information about the format of the HTTP request is to be found | |
114 | # here: http://www.no-ip.com/integrate/request and | |
115 | # here: http://www.no-ip.com/integrate/response | |
116 | ||
117 | url = "http://%(username)s:%(password)s@dynupdate.no-ip.com/nic/update?hostname=%(hostname)s&myip=%(address)s" | |
118 | ||
119 | def __call__(self): | |
120 | url = self.url % { | |
121 | "hostname" : self.hostname, | |
122 | "username" : self.username, | |
123 | "password" : self.password, | |
124 | "address" : self.get_address("ipv4"), | |
125 | } | |
126 | ||
127 | # Send update to the server. | |
128 | response = self.send_request(url) | |
129 | ||
130 | # Get the full response message. | |
131 | output = response.read() | |
132 | ||
133 | # Handle success messages. | |
134 | if output.startswith("good") or output.startswith("nochg"): | |
135 | return | |
136 | ||
137 | # Handle error codes. | |
138 | if output == "badauth": | |
139 | raise DDNSAuthenticationError | |
140 | elif output == "aduse": | |
141 | raise DDNSAbuseError | |
142 | elif output == "911": | |
143 | raise DDNSInternalServerError | |
144 | ||
145 | # If we got here, some other update error happened. | |
146 | raise DDNSUpdateError | |
147 | ||
148 | ||
149 | class DDNSProviderSelfhost(DDNSProvider): | |
150 | INFO = { | |
151 | "handle" : "selfhost.de", | |
152 | "name" : "Selfhost.de", | |
153 | "website" : "http://www.selfhost.de/", | |
154 | "protocols" : ["ipv4",], | |
155 | } | |
156 | ||
157 | url = "https://carol.selfhost.de/update?username=%(username)s&password=%(password)s&textmodi=1" | |
158 | ||
159 | def __call__(self): | |
160 | url = self.url % { "username" : self.username, "password" : self.password } | |
161 | ||
162 | response = self.send_request(url) | |
163 | ||
164 | match = re.search("status=20(0|4)", response.read()) | |
165 | if not match: | |
166 | raise DDNSUpdateError |