]> git.ipfire.org Git - oddments/ddns.git/blame - src/ddns/providers.py
Fix broken link.
[oddments/ddns.git] / src / ddns / providers.py
CommitLineData
f22ab085 1#!/usr/bin/python
3fdcb9d1
MT
2###############################################################################
3# #
4# ddns - A dynamic DNS client for IPFire #
5# Copyright (C) 2012 IPFire development team #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
f22ab085 21
7399fc5b 22import logging
3b16fdb1 23import urllib2
d1cd57eb 24import xml.dom.minidom
7399fc5b
MT
25
26from i18n import _
27
f22ab085
MT
28# Import all possible exception types.
29from .errors import *
30
7399fc5b
MT
31logger = logging.getLogger("ddns.providers")
32logger.propagate = 1
33
f22ab085 34class DDNSProvider(object):
6a11646e
MT
35 # A short string that uniquely identifies
36 # this provider.
37 handle = None
f22ab085 38
6a11646e
MT
39 # The full name of the provider.
40 name = None
f22ab085 41
6a11646e
MT
42 # A weburl to the homepage of the provider.
43 # (Where to register a new account?)
44 website = None
f22ab085 45
6a11646e
MT
46 # A list of supported protocols.
47 protocols = ("ipv6", "ipv4")
f22ab085
MT
48
49 DEFAULT_SETTINGS = {}
50
51 def __init__(self, core, **settings):
52 self.core = core
53
54 # Copy a set of default settings and
55 # update them by those from the configuration file.
56 self.settings = self.DEFAULT_SETTINGS.copy()
57 self.settings.update(settings)
58
59 def __repr__(self):
60 return "<DDNS Provider %s (%s)>" % (self.name, self.handle)
61
62 def __cmp__(self, other):
63 return cmp(self.hostname, other.hostname)
64
f22ab085
MT
65 def get(self, key, default=None):
66 """
67 Get a setting from the settings dictionary.
68 """
69 return self.settings.get(key, default)
70
71 @property
72 def hostname(self):
73 """
74 Fast access to the hostname.
75 """
76 return self.get("hostname")
77
78 @property
79 def username(self):
80 """
81 Fast access to the username.
82 """
83 return self.get("username")
84
85 @property
86 def password(self):
87 """
88 Fast access to the password.
89 """
90 return self.get("password")
91
46687828
SS
92 @property
93 def token(self):
94 """
95 Fast access to the token.
96 """
97 return self.get("token")
98
9da3e685
MT
99 def __call__(self, force=False):
100 if force:
c3888f15 101 logger.debug(_("Updating %s forced") % self.hostname)
9da3e685 102
7399fc5b 103 # Check if we actually need to update this host.
9da3e685 104 elif self.is_uptodate(self.protocols):
c3888f15 105 logger.debug(_("%s is already up to date") % self.hostname)
7399fc5b
MT
106 return
107
108 # Execute the update.
5f402f36
MT
109 self.update()
110
111 def update(self):
f22ab085
MT
112 raise NotImplementedError
113
7399fc5b
MT
114 def is_uptodate(self, protos):
115 """
116 Returns True if this host is already up to date
117 and does not need to change the IP address on the
118 name server.
119 """
120 for proto in protos:
121 addresses = self.core.system.resolve(self.hostname, proto)
122
123 current_address = self.get_address(proto)
124
38d81db4
MT
125 # If no addresses for the given protocol exist, we
126 # are fine...
127 if current_address is None and not addresses:
128 continue
129
7399fc5b
MT
130 if not current_address in addresses:
131 return False
132
133 return True
134
f22ab085
MT
135 def send_request(self, *args, **kwargs):
136 """
137 Proxy connection to the send request
138 method.
139 """
140 return self.core.system.send_request(*args, **kwargs)
141
e3c70807 142 def get_address(self, proto, default=None):
f22ab085
MT
143 """
144 Proxy method to get the current IP address.
145 """
e3c70807 146 return self.core.system.get_address(proto) or default
f22ab085
MT
147
148
5d4bec40
MT
149class DDNSProtocolDynDNS2(object):
150 """
151 This is an abstract class that implements the DynDNS updater
152 protocol version 2. As this is a popular way to update dynamic
153 DNS records, this class is supposed make the provider classes
154 shorter and simpler.
155 """
156
157 # Information about the format of the request is to be found
486c1b9d 158 # http://dyn.com/support/developers/api/perform-update/
5d4bec40
MT
159 # http://dyn.com/support/developers/api/return-codes/
160
161 def _prepare_request_data(self):
162 data = {
163 "hostname" : self.hostname,
164 "myip" : self.get_address("ipv4"),
165 }
166
167 return data
168
169 def update(self):
170 data = self._prepare_request_data()
171
172 # Send update to the server.
173 response = self.send_request(self.url, data=data,
174 username=self.username, password=self.password)
175
176 # Get the full response message.
177 output = response.read()
178
179 # Handle success messages.
180 if output.startswith("good") or output.startswith("nochg"):
181 return
182
183 # Handle error codes.
184 if output == "badauth":
185 raise DDNSAuthenticationError
186 elif output == "aduse":
187 raise DDNSAbuseError
188 elif output == "notfqdn":
189 raise DDNSRequestError(_("No valid FQDN was given."))
190 elif output == "nohost":
191 raise DDNSRequestError(_("Specified host does not exist."))
192 elif output == "911":
193 raise DDNSInternalServerError
194 elif output == "dnserr":
195 raise DDNSInternalServerError(_("DNS error encountered."))
196
197 # If we got here, some other update error happened.
198 raise DDNSUpdateError(_("Server response: %s") % output)
199
200
3b16fdb1 201class DDNSProviderAllInkl(DDNSProvider):
6a11646e
MT
202 handle = "all-inkl.com"
203 name = "All-inkl.com"
204 website = "http://all-inkl.com/"
205 protocols = ("ipv4",)
3b16fdb1
SS
206
207 # There are only information provided by the vendor how to
208 # perform an update on a FRITZ Box. Grab requried informations
209 # from the net.
210 # http://all-inkl.goetze.it/v01/ddns-mit-einfachen-mitteln/
211
212 url = "http://dyndns.kasserver.com"
213
214 def update(self):
3b16fdb1
SS
215 # There is no additional data required so we directly can
216 # send our request.
536e87d1 217 response = self.send_request(self.url, username=self.username, password=self.password)
3b16fdb1
SS
218
219 # Get the full response message.
220 output = response.read()
221
222 # Handle success messages.
223 if output.startswith("good") or output.startswith("nochg"):
224 return
225
226 # If we got here, some other update error happened.
227 raise DDNSUpdateError
228
229
f3cf1f70 230class DDNSProviderDHS(DDNSProvider):
6a11646e
MT
231 handle = "dhs.org"
232 name = "DHS International"
233 website = "http://dhs.org/"
234 protocols = ("ipv4",)
f3cf1f70
SS
235
236 # No information about the used update api provided on webpage,
237 # grabed from source code of ez-ipudate.
b2b05ef3 238
f3cf1f70
SS
239 url = "http://members.dhs.org/nic/hosts"
240
5f402f36 241 def update(self):
f3cf1f70
SS
242 data = {
243 "domain" : self.hostname,
244 "ip" : self.get_address("ipv4"),
245 "hostcmd" : "edit",
246 "hostcmdstage" : "2",
247 "type" : "4",
248 }
249
250 # Send update to the server.
175c9b80 251 response = self.send_request(self.url, username=self.username, password=self.password,
f3cf1f70
SS
252 data=data)
253
254 # Handle success messages.
255 if response.code == 200:
256 return
257
f3cf1f70
SS
258 # If we got here, some other update error happened.
259 raise DDNSUpdateError
260
261
39301272 262class DDNSProviderDNSpark(DDNSProvider):
6a11646e
MT
263 handle = "dnspark.com"
264 name = "DNS Park"
265 website = "http://dnspark.com/"
266 protocols = ("ipv4",)
39301272
SS
267
268 # Informations to the used api can be found here:
269 # https://dnspark.zendesk.com/entries/31229348-Dynamic-DNS-API-Documentation
b2b05ef3 270
39301272
SS
271 url = "https://control.dnspark.com/api/dynamic/update.php"
272
5f402f36 273 def update(self):
39301272
SS
274 data = {
275 "domain" : self.hostname,
276 "ip" : self.get_address("ipv4"),
277 }
278
279 # Send update to the server.
175c9b80 280 response = self.send_request(self.url, username=self.username, password=self.password,
39301272
SS
281 data=data)
282
283 # Get the full response message.
284 output = response.read()
285
286 # Handle success messages.
287 if output.startswith("ok") or output.startswith("nochange"):
288 return
289
290 # Handle error codes.
291 if output == "unauth":
292 raise DDNSAuthenticationError
293 elif output == "abuse":
294 raise DDNSAbuseError
295 elif output == "blocked":
296 raise DDNSBlockedError
297 elif output == "nofqdn":
298 raise DDNSRequestError(_("No valid FQDN was given."))
299 elif output == "nohost":
300 raise DDNSRequestError(_("Invalid hostname specified."))
301 elif output == "notdyn":
302 raise DDNSRequestError(_("Hostname not marked as a dynamic host."))
303 elif output == "invalid":
304 raise DDNSRequestError(_("Invalid IP address has been sent."))
305
306 # If we got here, some other update error happened.
307 raise DDNSUpdateError
308
43b2cd59
SS
309
310class DDNSProviderDtDNS(DDNSProvider):
6a11646e
MT
311 handle = "dtdns.com"
312 name = "DtDNS"
313 website = "http://dtdns.com/"
314 protocols = ("ipv4",)
43b2cd59
SS
315
316 # Information about the format of the HTTPS request is to be found
317 # http://www.dtdns.com/dtsite/updatespec
b2b05ef3 318
43b2cd59
SS
319 url = "https://www.dtdns.com/api/autodns.cfm"
320
43b2cd59
SS
321 def update(self):
322 data = {
323 "ip" : self.get_address("ipv4"),
324 "id" : self.hostname,
325 "pw" : self.password
326 }
327
328 # Send update to the server.
329 response = self.send_request(self.url, data=data)
330
331 # Get the full response message.
332 output = response.read()
333
334 # Remove all leading and trailing whitespace.
335 output = output.strip()
336
337 # Handle success messages.
338 if "now points to" in output:
339 return
340
341 # Handle error codes.
342 if output == "No hostname to update was supplied.":
343 raise DDNSRequestError(_("No hostname specified."))
344
345 elif output == "The hostname you supplied is not valid.":
346 raise DDNSRequestError(_("Invalid hostname specified."))
347
348 elif output == "The password you supplied is not valid.":
349 raise DDNSAuthenticationError
350
351 elif output == "Administration has disabled this account.":
352 raise DDNSRequestError(_("Account has been disabled."))
353
354 elif output == "Illegal character in IP.":
355 raise DDNSRequestError(_("Invalid IP address has been sent."))
356
357 elif output == "Too many failed requests.":
358 raise DDNSRequestError(_("Too many failed requests."))
359
360 # If we got here, some other update error happened.
361 raise DDNSUpdateError
362
363
5d4bec40 364class DDNSProviderDynDNS(DDNSProtocolDynDNS2, DDNSProvider):
6a11646e
MT
365 handle = "dyndns.org"
366 name = "Dyn"
367 website = "http://dyn.com/dns/"
368 protocols = ("ipv4",)
bfed6701
SS
369
370 # Information about the format of the request is to be found
371 # http://http://dyn.com/support/developers/api/perform-update/
372 # http://dyn.com/support/developers/api/return-codes/
b2b05ef3 373
bfed6701
SS
374 url = "https://members.dyndns.org/nic/update"
375
bfed6701 376
5d4bec40 377class DDNSProviderDynU(DDNSProtocolDynDNS2, DDNSProvider):
6a11646e
MT
378 handle = "dynu.com"
379 name = "Dynu"
380 website = "http://dynu.com/"
381 protocols = ("ipv6", "ipv4",)
3a8407fa
SS
382
383 # Detailed information about the request and response codes
384 # are available on the providers webpage.
385 # http://dynu.com/Default.aspx?page=dnsapi
386
387 url = "https://api.dynu.com/nic/update"
388
389 def _prepare_request_data(self):
54d3efc8
MT
390 data = DDNSProviderDynDNS._prepare_request_data(self)
391
392 # This one supports IPv6
393 data.update({
3a8407fa 394 "myipv6" : self.get_address("ipv6"),
54d3efc8
MT
395 })
396
397 return data
3a8407fa
SS
398
399
5d4bec40
MT
400class DDNSProviderEasyDNS(DDNSProtocolDynDNS2, DDNSProvider):
401 handle = "easydns.com"
402 name = "EasyDNS"
403 website = "http://www.easydns.com/"
404 protocols = ("ipv4",)
ee071271
SS
405
406 # There is only some basic documentation provided by the vendor,
407 # also searching the web gain very poor results.
408 # http://mediawiki.easydns.com/index.php/Dynamic_DNS
409
410 url = "http://api.cp.easydns.com/dyn/tomato.php"
411
412
aa21a4c6 413class DDNSProviderFreeDNSAfraidOrg(DDNSProvider):
6a11646e
MT
414 handle = "freedns.afraid.org"
415 name = "freedns.afraid.org"
416 website = "http://freedns.afraid.org/"
aa21a4c6
SS
417
418 # No information about the request or response could be found on the vendor
419 # page. All used values have been collected by testing.
420 url = "https://freedns.afraid.org/dynamic/update.php"
421
422 @property
423 def proto(self):
424 return self.get("proto")
425
426 def update(self):
427 address = self.get_address(self.proto)
428
429 data = {
430 "address" : address,
431 }
432
433 # Add auth token to the update url.
434 url = "%s?%s" % (self.url, self.token)
435
436 # Send update to the server.
437 response = self.send_request(url, data=data)
438
aa21a4c6
SS
439 if output.startswith("Updated") or "has not changed" in output:
440 return
441
442 # Handle error codes.
443 if output == "ERROR: Unable to locate this record":
444 raise DDNSAuthenticationError
445 elif "is an invalid IP address" in output:
446 raise DDNSRequestError(_("Invalid IP address has been sent."))
447
3b524cf2
SS
448 # If we got here, some other update error happened.
449 raise DDNSUpdateError
450
aa21a4c6 451
a08c1b72 452class DDNSProviderLightningWireLabs(DDNSProvider):
6a11646e 453 handle = "dns.lightningwirelabs.com"
fb115fdc 454 name = "Lightning Wire Labs DNS Service"
6a11646e 455 website = "http://dns.lightningwirelabs.com/"
a08c1b72
SS
456
457 # Information about the format of the HTTPS request is to be found
458 # https://dns.lightningwirelabs.com/knowledge-base/api/ddns
b2b05ef3 459
a08c1b72
SS
460 url = "https://dns.lightningwirelabs.com/update"
461
5f402f36 462 def update(self):
a08c1b72
SS
463 data = {
464 "hostname" : self.hostname,
e3c70807
MT
465 "address6" : self.get_address("ipv6", "-"),
466 "address4" : self.get_address("ipv4", "-"),
a08c1b72
SS
467 }
468
a08c1b72
SS
469 # Check if a token has been set.
470 if self.token:
471 data["token"] = self.token
472
473 # Check for username and password.
474 elif self.username and self.password:
475 data.update({
476 "username" : self.username,
477 "password" : self.password,
478 })
479
480 # Raise an error if no auth details are given.
481 else:
482 raise DDNSConfigurationError
483
484 # Send update to the server.
cb455540 485 response = self.send_request(self.url, data=data)
a08c1b72
SS
486
487 # Handle success messages.
488 if response.code == 200:
489 return
490
a08c1b72
SS
491 # If we got here, some other update error happened.
492 raise DDNSUpdateError
493
494
d1cd57eb 495class DDNSProviderNamecheap(DDNSProvider):
6a11646e
MT
496 handle = "namecheap.com"
497 name = "Namecheap"
498 website = "http://namecheap.com"
499 protocols = ("ipv4",)
d1cd57eb
SS
500
501 # Information about the format of the HTTP request is to be found
502 # https://www.namecheap.com/support/knowledgebase/article.aspx/9249/0/nc-dynamic-dns-to-dyndns-adapter
503 # https://community.namecheap.com/forums/viewtopic.php?f=6&t=6772
504
505 url = "https://dynamicdns.park-your-domain.com/update"
506
507 def parse_xml(self, document, content):
508 # Send input to the parser.
509 xmldoc = xml.dom.minidom.parseString(document)
510
511 # Get XML elements by the given content.
512 element = xmldoc.getElementsByTagName(content)
513
514 # If no element has been found, we directly can return None.
515 if not element:
516 return None
517
518 # Only get the first child from an element, even there are more than one.
519 firstchild = element[0].firstChild
520
521 # Get the value of the child.
522 value = firstchild.nodeValue
523
524 # Return the value.
525 return value
526
527 def update(self):
528 # Namecheap requires the hostname splitted into a host and domain part.
529 host, domain = self.hostname.split(".", 1)
530
531 data = {
532 "ip" : self.get_address("ipv4"),
533 "password" : self.password,
534 "host" : host,
535 "domain" : domain
536 }
537
538 # Send update to the server.
539 response = self.send_request(self.url, data=data)
540
541 # Get the full response message.
542 output = response.read()
543
544 # Handle success messages.
545 if self.parse_xml(output, "IP") == self.get_address("ipv4"):
546 return
547
548 # Handle error codes.
549 errorcode = self.parse_xml(output, "ResponseNumber")
550
551 if errorcode == "304156":
552 raise DDNSAuthenticationError
553 elif errorcode == "316153":
554 raise DDNSRequestError(_("Domain not found."))
555 elif errorcode == "316154":
556 raise DDNSRequestError(_("Domain not active."))
557 elif errorcode in ("380098", "380099"):
558 raise DDNSInternalServerError
559
560 # If we got here, some other update error happened.
561 raise DDNSUpdateError
562
563
5d4bec40
MT
564class DDNSProviderNOIP(DDNSProtocolDynDNS2, DDNSProvider):
565 handle = "no-ip.com"
566 name = "No-IP"
567 website = "http://www.no-ip.com/"
568 protocols = ("ipv4",)
f22ab085
MT
569
570 # Information about the format of the HTTP request is to be found
571 # here: http://www.no-ip.com/integrate/request and
572 # here: http://www.no-ip.com/integrate/response
573
88f39629 574 url = "http://dynupdate.no-ip.com/nic/update"
2de06f59 575
88f39629 576 def _prepare_request_data(self):
2de06f59
MT
577 data = {
578 "hostname" : self.hostname,
f22ab085
MT
579 "address" : self.get_address("ipv4"),
580 }
581
88f39629 582 return data
f22ab085
MT
583
584
5d4bec40
MT
585class DDNSProviderOVH(DDNSProtocolDynDNS2, DDNSProvider):
586 handle = "ovh.com"
587 name = "OVH"
588 website = "http://www.ovh.com/"
589 protocols = ("ipv4",)
a508bda6
SS
590
591 # OVH only provides very limited information about how to
592 # update a DynDNS host. They only provide the update url
593 # on the their german subpage.
594 #
595 # http://hilfe.ovh.de/DomainDynHost
596
597 url = "https://www.ovh.com/nic/update"
598
599 def _prepare_request_data(self):
5d4bec40 600 data = DDNSProtocolDynDNS2._prepare_request_data(self)
54d3efc8
MT
601 data.update({
602 "system" : "dyndns",
603 })
604
605 return data
a508bda6
SS
606
607
ef33455e 608class DDNSProviderRegfish(DDNSProvider):
6a11646e
MT
609 handle = "regfish.com"
610 name = "Regfish GmbH"
611 website = "http://www.regfish.com/"
ef33455e
SS
612
613 # A full documentation to the providers api can be found here
614 # but is only available in german.
615 # https://www.regfish.de/domains/dyndns/dokumentation
616
617 url = "https://dyndns.regfish.de/"
618
619 def update(self):
620 data = {
621 "fqdn" : self.hostname,
622 }
623
624 # Check if we update an IPv6 address.
625 address6 = self.get_address("ipv6")
626 if address6:
627 data["ipv6"] = address6
628
629 # Check if we update an IPv4 address.
630 address4 = self.get_address("ipv4")
631 if address4:
632 data["ipv4"] = address4
633
634 # Raise an error if none address is given.
635 if not data.has_key("ipv6") and not data.has_key("ipv4"):
636 raise DDNSConfigurationError
637
638 # Check if a token has been set.
639 if self.token:
640 data["token"] = self.token
641
642 # Raise an error if no token and no useranem and password
643 # are given.
644 elif not self.username and not self.password:
645 raise DDNSConfigurationError(_("No Auth details specified."))
646
647 # HTTP Basic Auth is only allowed if no token is used.
648 if self.token:
649 # Send update to the server.
650 response = self.send_request(self.url, data=data)
651 else:
652 # Send update to the server.
653 response = self.send_request(self.url, username=self.username, password=self.password,
654 data=data)
655
656 # Get the full response message.
657 output = response.read()
658
659 # Handle success messages.
660 if "100" in output or "101" in output:
661 return
662
663 # Handle error codes.
664 if "401" or "402" in output:
665 raise DDNSAuthenticationError
666 elif "408" in output:
667 raise DDNSRequestError(_("Invalid IPv4 address has been sent."))
668 elif "409" in output:
669 raise DDNSRequestError(_("Invalid IPv6 address has been sent."))
670 elif "412" in output:
671 raise DDNSRequestError(_("No valid FQDN was given."))
672 elif "414" in output:
673 raise DDNSInternalServerError
674
675 # If we got here, some other update error happened.
676 raise DDNSUpdateError
677
678
5d4bec40 679class DDNSProviderSelfhost(DDNSProtocolDynDNS2, DDNSProvider):
6a11646e
MT
680 handle = "selfhost.de"
681 name = "Selfhost.de"
682 website = "http://www.selfhost.de/"
5d4bec40 683 protocols = ("ipv4",)
f22ab085 684
04db1862 685 url = "https://carol.selfhost.de/nic/update"
f22ab085 686
04db1862
MT
687 def _prepare_request_data(self):
688 data = DDNSProviderDynDNS._prepare_request_data(self)
689 data.update({
690 "hostname" : "1",
691 })
f22ab085 692
04db1862 693 return data
b09b1545
SS
694
695
5d4bec40
MT
696class DDNSProviderSPDNS(DDNSProtocolDynDNS2, DDNSProvider):
697 handle = "spdns.org"
698 name = "SPDNS"
699 website = "http://spdns.org/"
700 protocols = ("ipv4",)
b09b1545
SS
701
702 # Detailed information about request and response codes are provided
703 # by the vendor. They are using almost the same mechanism and status
704 # codes as dyndns.org so we can inherit all those stuff.
705 #
706 # http://wiki.securepoint.de/index.php/SPDNS_FAQ
707 # http://wiki.securepoint.de/index.php/SPDNS_Update-Tokens
708
709 url = "https://update.spdns.de/nic/update"
4ec90b93
MT
710
711
5d4bec40
MT
712class DDNSProviderStrato(DDNSProtocolDynDNS2, DDNSProvider):
713 handle = "strato.com"
714 name = "Strato AG"
715 website = "http:/www.strato.com/"
716 protocols = ("ipv4",)
7488825c
SS
717
718 # Information about the request and response can be obtained here:
719 # http://www.strato-faq.de/article/671/So-einfach-richten-Sie-DynDNS-f%C3%BCr-Ihre-Domains-ein.html
720
721 url = "https://dyndns.strato.com/nic/update"
722
723
5d4bec40
MT
724class DDNSProviderTwoDNS(DDNSProtocolDynDNS2, DDNSProvider):
725 handle = "twodns.de"
726 name = "TwoDNS"
727 website = "http://www.twodns.de"
728 protocols = ("ipv4",)
a6183090
SS
729
730 # Detailed information about the request can be found here
731 # http://twodns.de/en/faqs
732 # http://twodns.de/en/api
733
734 url = "https://update.twodns.de/update"
735
736 def _prepare_request_data(self):
737 data = {
738 "ip" : self.get_address("ipv4"),
739 "hostname" : self.hostname
740 }
741
742 return data
743
744
5d4bec40
MT
745class DDNSProviderUdmedia(DDNSProtocolDynDNS2, DDNSProvider):
746 handle = "udmedia.de"
747 name = "Udmedia GmbH"
748 website = "http://www.udmedia.de"
749 protocols = ("ipv4",)
03bdd188
SS
750
751 # Information about the request can be found here
752 # http://www.udmedia.de/faq/content/47/288/de/wie-lege-ich-einen-dyndns_eintrag-an.html
753
754 url = "https://www.udmedia.de/nic/update"
755
756
5d4bec40 757class DDNSProviderVariomedia(DDNSProtocolDynDNS2, DDNSProvider):
6a11646e
MT
758 handle = "variomedia.de"
759 name = "Variomedia"
760 website = "http://www.variomedia.de/"
761 protocols = ("ipv6", "ipv4",)
c8c7ca8f
SS
762
763 # Detailed information about the request can be found here
764 # https://dyndns.variomedia.de/
765
766 url = "https://dyndns.variomedia.de/nic/update"
767
768 @property
769 def proto(self):
770 return self.get("proto")
771
772 def _prepare_request_data(self):
773 data = {
774 "hostname" : self.hostname,
775 "myip" : self.get_address(self.proto)
776 }
54d3efc8
MT
777
778 return data
98fbe467
SS
779
780
5d4bec40
MT
781class DDNSProviderZoneedit(DDNSProtocolDynDNS2, DDNSProvider):
782 handle = "zoneedit.com"
783 name = "Zoneedit"
784 website = "http://www.zoneedit.com"
785 protocols = ("ipv4",)
98fbe467
SS
786
787 # Detailed information about the request and the response codes can be
788 # obtained here:
789 # http://www.zoneedit.com/doc/api/other.html
790 # http://www.zoneedit.com/faq.html
791
792 url = "https://dynamic.zoneedit.com/auth/dynamic.html"
793
794 @property
795 def proto(self):
796 return self.get("proto")
797
798 def update(self):
799 data = {
800 "dnsto" : self.get_address(self.proto),
801 "host" : self.hostname
802 }
803
804 # Send update to the server.
805 response = self.send_request(self.url, username=self.username, password=self.password,
806 data=data)
807
808 # Get the full response message.
809 output = response.read()
810
811 # Handle success messages.
812 if output.startswith("<SUCCESS"):
813 return
814
815 # Handle error codes.
816 if output.startswith("invalid login"):
817 raise DDNSAuthenticationError
818 elif output.startswith("<ERROR CODE=\"704\""):
819 raise DDNSRequestError(_("No valid FQDN was given."))
820 elif output.startswith("<ERROR CODE=\"702\""):
821 raise DDNSInternalServerError
822
823 # If we got here, some other update error happened.
824 raise DDNSUpdateError