freedns.afraid.com: Read accidently removed exeption.
[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
3b16fdb1 149class DDNSProviderAllInkl(DDNSProvider):
6a11646e
MT
150 handle = "all-inkl.com"
151 name = "All-inkl.com"
152 website = "http://all-inkl.com/"
153 protocols = ("ipv4",)
3b16fdb1
SS
154
155 # There are only information provided by the vendor how to
156 # perform an update on a FRITZ Box. Grab requried informations
157 # from the net.
158 # http://all-inkl.goetze.it/v01/ddns-mit-einfachen-mitteln/
159
160 url = "http://dyndns.kasserver.com"
161
162 def update(self):
3b16fdb1
SS
163 # There is no additional data required so we directly can
164 # send our request.
536e87d1 165 response = self.send_request(self.url, username=self.username, password=self.password)
3b16fdb1
SS
166
167 # Get the full response message.
168 output = response.read()
169
170 # Handle success messages.
171 if output.startswith("good") or output.startswith("nochg"):
172 return
173
174 # If we got here, some other update error happened.
175 raise DDNSUpdateError
176
177
f3cf1f70 178class DDNSProviderDHS(DDNSProvider):
6a11646e
MT
179 handle = "dhs.org"
180 name = "DHS International"
181 website = "http://dhs.org/"
182 protocols = ("ipv4",)
f3cf1f70
SS
183
184 # No information about the used update api provided on webpage,
185 # grabed from source code of ez-ipudate.
186 url = "http://members.dhs.org/nic/hosts"
187
5f402f36 188 def update(self):
f3cf1f70
SS
189 data = {
190 "domain" : self.hostname,
191 "ip" : self.get_address("ipv4"),
192 "hostcmd" : "edit",
193 "hostcmdstage" : "2",
194 "type" : "4",
195 }
196
197 # Send update to the server.
175c9b80 198 response = self.send_request(self.url, username=self.username, password=self.password,
f3cf1f70
SS
199 data=data)
200
201 # Handle success messages.
202 if response.code == 200:
203 return
204
f3cf1f70
SS
205 # If we got here, some other update error happened.
206 raise DDNSUpdateError
207
208
39301272 209class DDNSProviderDNSpark(DDNSProvider):
6a11646e
MT
210 handle = "dnspark.com"
211 name = "DNS Park"
212 website = "http://dnspark.com/"
213 protocols = ("ipv4",)
39301272
SS
214
215 # Informations to the used api can be found here:
216 # https://dnspark.zendesk.com/entries/31229348-Dynamic-DNS-API-Documentation
217 url = "https://control.dnspark.com/api/dynamic/update.php"
218
5f402f36 219 def update(self):
39301272
SS
220 data = {
221 "domain" : self.hostname,
222 "ip" : self.get_address("ipv4"),
223 }
224
225 # Send update to the server.
175c9b80 226 response = self.send_request(self.url, username=self.username, password=self.password,
39301272
SS
227 data=data)
228
229 # Get the full response message.
230 output = response.read()
231
232 # Handle success messages.
233 if output.startswith("ok") or output.startswith("nochange"):
234 return
235
236 # Handle error codes.
237 if output == "unauth":
238 raise DDNSAuthenticationError
239 elif output == "abuse":
240 raise DDNSAbuseError
241 elif output == "blocked":
242 raise DDNSBlockedError
243 elif output == "nofqdn":
244 raise DDNSRequestError(_("No valid FQDN was given."))
245 elif output == "nohost":
246 raise DDNSRequestError(_("Invalid hostname specified."))
247 elif output == "notdyn":
248 raise DDNSRequestError(_("Hostname not marked as a dynamic host."))
249 elif output == "invalid":
250 raise DDNSRequestError(_("Invalid IP address has been sent."))
251
252 # If we got here, some other update error happened.
253 raise DDNSUpdateError
254
43b2cd59
SS
255
256class DDNSProviderDtDNS(DDNSProvider):
6a11646e
MT
257 handle = "dtdns.com"
258 name = "DtDNS"
259 website = "http://dtdns.com/"
260 protocols = ("ipv4",)
43b2cd59
SS
261
262 # Information about the format of the HTTPS request is to be found
263 # http://www.dtdns.com/dtsite/updatespec
264 url = "https://www.dtdns.com/api/autodns.cfm"
265
43b2cd59
SS
266 def update(self):
267 data = {
268 "ip" : self.get_address("ipv4"),
269 "id" : self.hostname,
270 "pw" : self.password
271 }
272
273 # Send update to the server.
274 response = self.send_request(self.url, data=data)
275
276 # Get the full response message.
277 output = response.read()
278
279 # Remove all leading and trailing whitespace.
280 output = output.strip()
281
282 # Handle success messages.
283 if "now points to" in output:
284 return
285
286 # Handle error codes.
287 if output == "No hostname to update was supplied.":
288 raise DDNSRequestError(_("No hostname specified."))
289
290 elif output == "The hostname you supplied is not valid.":
291 raise DDNSRequestError(_("Invalid hostname specified."))
292
293 elif output == "The password you supplied is not valid.":
294 raise DDNSAuthenticationError
295
296 elif output == "Administration has disabled this account.":
297 raise DDNSRequestError(_("Account has been disabled."))
298
299 elif output == "Illegal character in IP.":
300 raise DDNSRequestError(_("Invalid IP address has been sent."))
301
302 elif output == "Too many failed requests.":
303 raise DDNSRequestError(_("Too many failed requests."))
304
305 # If we got here, some other update error happened.
306 raise DDNSUpdateError
307
308
bfed6701 309class DDNSProviderDynDNS(DDNSProvider):
6a11646e
MT
310 handle = "dyndns.org"
311 name = "Dyn"
312 website = "http://dyn.com/dns/"
313 protocols = ("ipv4",)
bfed6701
SS
314
315 # Information about the format of the request is to be found
316 # http://http://dyn.com/support/developers/api/perform-update/
317 # http://dyn.com/support/developers/api/return-codes/
318 url = "https://members.dyndns.org/nic/update"
319
88f39629 320 def _prepare_request_data(self):
bfed6701
SS
321 data = {
322 "hostname" : self.hostname,
323 "myip" : self.get_address("ipv4"),
324 }
325
88f39629
SS
326 return data
327
328 def update(self):
329 data = self._prepare_request_data()
330
bfed6701 331 # Send update to the server.
88f39629
SS
332 response = self.send_request(self.url, data=data,
333 username=self.username, password=self.password)
bfed6701
SS
334
335 # Get the full response message.
336 output = response.read()
337
338 # Handle success messages.
339 if output.startswith("good") or output.startswith("nochg"):
340 return
341
342 # Handle error codes.
343 if output == "badauth":
344 raise DDNSAuthenticationError
345 elif output == "aduse":
346 raise DDNSAbuseError
347 elif output == "notfqdn":
348 raise DDNSRequestError(_("No valid FQDN was given."))
349 elif output == "nohost":
350 raise DDNSRequestError(_("Specified host does not exist."))
351 elif output == "911":
352 raise DDNSInternalServerError
353 elif output == "dnserr":
354 raise DDNSInternalServerError(_("DNS error encountered."))
355
356 # If we got here, some other update error happened.
0271a97f 357 raise DDNSUpdateError(_("Server response: %s") % output)
bfed6701
SS
358
359
3a8407fa 360class DDNSProviderDynU(DDNSProviderDynDNS):
6a11646e
MT
361 handle = "dynu.com"
362 name = "Dynu"
363 website = "http://dynu.com/"
364 protocols = ("ipv6", "ipv4",)
3a8407fa
SS
365
366 # Detailed information about the request and response codes
367 # are available on the providers webpage.
368 # http://dynu.com/Default.aspx?page=dnsapi
369
370 url = "https://api.dynu.com/nic/update"
371
372 def _prepare_request_data(self):
54d3efc8
MT
373 data = DDNSProviderDynDNS._prepare_request_data(self)
374
375 # This one supports IPv6
376 data.update({
3a8407fa 377 "myipv6" : self.get_address("ipv6"),
54d3efc8
MT
378 })
379
380 return data
3a8407fa
SS
381
382
ee071271 383class DDNSProviderEasyDNS(DDNSProviderDynDNS):
6a11646e
MT
384 handle = "easydns.com"
385 name = "EasyDNS"
386 website = "http://www.easydns.com/"
ee071271
SS
387
388 # There is only some basic documentation provided by the vendor,
389 # also searching the web gain very poor results.
390 # http://mediawiki.easydns.com/index.php/Dynamic_DNS
391
392 url = "http://api.cp.easydns.com/dyn/tomato.php"
393
394
aa21a4c6 395class DDNSProviderFreeDNSAfraidOrg(DDNSProvider):
6a11646e
MT
396 handle = "freedns.afraid.org"
397 name = "freedns.afraid.org"
398 website = "http://freedns.afraid.org/"
aa21a4c6
SS
399
400 # No information about the request or response could be found on the vendor
401 # page. All used values have been collected by testing.
402 url = "https://freedns.afraid.org/dynamic/update.php"
403
404 @property
405 def proto(self):
406 return self.get("proto")
407
408 def update(self):
409 address = self.get_address(self.proto)
410
411 data = {
412 "address" : address,
413 }
414
415 # Add auth token to the update url.
416 url = "%s?%s" % (self.url, self.token)
417
418 # Send update to the server.
419 response = self.send_request(url, data=data)
420
aa21a4c6
SS
421 if output.startswith("Updated") or "has not changed" in output:
422 return
423
424 # Handle error codes.
425 if output == "ERROR: Unable to locate this record":
426 raise DDNSAuthenticationError
427 elif "is an invalid IP address" in output:
428 raise DDNSRequestError(_("Invalid IP address has been sent."))
429
3b524cf2
SS
430 # If we got here, some other update error happened.
431 raise DDNSUpdateError
432
aa21a4c6 433
a08c1b72 434class DDNSProviderLightningWireLabs(DDNSProvider):
6a11646e 435 handle = "dns.lightningwirelabs.com"
fb115fdc 436 name = "Lightning Wire Labs DNS Service"
6a11646e 437 website = "http://dns.lightningwirelabs.com/"
a08c1b72
SS
438
439 # Information about the format of the HTTPS request is to be found
440 # https://dns.lightningwirelabs.com/knowledge-base/api/ddns
441 url = "https://dns.lightningwirelabs.com/update"
442
5f402f36 443 def update(self):
a08c1b72
SS
444 data = {
445 "hostname" : self.hostname,
e3c70807
MT
446 "address6" : self.get_address("ipv6", "-"),
447 "address4" : self.get_address("ipv4", "-"),
a08c1b72
SS
448 }
449
a08c1b72
SS
450 # Check if a token has been set.
451 if self.token:
452 data["token"] = self.token
453
454 # Check for username and password.
455 elif self.username and self.password:
456 data.update({
457 "username" : self.username,
458 "password" : self.password,
459 })
460
461 # Raise an error if no auth details are given.
462 else:
463 raise DDNSConfigurationError
464
465 # Send update to the server.
cb455540 466 response = self.send_request(self.url, data=data)
a08c1b72
SS
467
468 # Handle success messages.
469 if response.code == 200:
470 return
471
a08c1b72
SS
472 # If we got here, some other update error happened.
473 raise DDNSUpdateError
474
475
d1cd57eb 476class DDNSProviderNamecheap(DDNSProvider):
6a11646e
MT
477 handle = "namecheap.com"
478 name = "Namecheap"
479 website = "http://namecheap.com"
480 protocols = ("ipv4",)
d1cd57eb
SS
481
482 # Information about the format of the HTTP request is to be found
483 # https://www.namecheap.com/support/knowledgebase/article.aspx/9249/0/nc-dynamic-dns-to-dyndns-adapter
484 # https://community.namecheap.com/forums/viewtopic.php?f=6&t=6772
485
486 url = "https://dynamicdns.park-your-domain.com/update"
487
488 def parse_xml(self, document, content):
489 # Send input to the parser.
490 xmldoc = xml.dom.minidom.parseString(document)
491
492 # Get XML elements by the given content.
493 element = xmldoc.getElementsByTagName(content)
494
495 # If no element has been found, we directly can return None.
496 if not element:
497 return None
498
499 # Only get the first child from an element, even there are more than one.
500 firstchild = element[0].firstChild
501
502 # Get the value of the child.
503 value = firstchild.nodeValue
504
505 # Return the value.
506 return value
507
508 def update(self):
509 # Namecheap requires the hostname splitted into a host and domain part.
510 host, domain = self.hostname.split(".", 1)
511
512 data = {
513 "ip" : self.get_address("ipv4"),
514 "password" : self.password,
515 "host" : host,
516 "domain" : domain
517 }
518
519 # Send update to the server.
520 response = self.send_request(self.url, data=data)
521
522 # Get the full response message.
523 output = response.read()
524
525 # Handle success messages.
526 if self.parse_xml(output, "IP") == self.get_address("ipv4"):
527 return
528
529 # Handle error codes.
530 errorcode = self.parse_xml(output, "ResponseNumber")
531
532 if errorcode == "304156":
533 raise DDNSAuthenticationError
534 elif errorcode == "316153":
535 raise DDNSRequestError(_("Domain not found."))
536 elif errorcode == "316154":
537 raise DDNSRequestError(_("Domain not active."))
538 elif errorcode in ("380098", "380099"):
539 raise DDNSInternalServerError
540
541 # If we got here, some other update error happened.
542 raise DDNSUpdateError
543
544
88f39629 545class DDNSProviderNOIP(DDNSProviderDynDNS):
6a11646e
MT
546 handle = "no-ip.com"
547 name = "No-IP"
548 website = "http://www.no-ip.com/"
f22ab085
MT
549
550 # Information about the format of the HTTP request is to be found
551 # here: http://www.no-ip.com/integrate/request and
552 # here: http://www.no-ip.com/integrate/response
553
88f39629 554 url = "http://dynupdate.no-ip.com/nic/update"
2de06f59 555
88f39629 556 def _prepare_request_data(self):
2de06f59
MT
557 data = {
558 "hostname" : self.hostname,
f22ab085
MT
559 "address" : self.get_address("ipv4"),
560 }
561
88f39629 562 return data
f22ab085
MT
563
564
a508bda6 565class DDNSProviderOVH(DDNSProviderDynDNS):
6a11646e
MT
566 handle = "ovh.com"
567 name = "OVH"
568 website = "http://www.ovh.com/"
a508bda6
SS
569
570 # OVH only provides very limited information about how to
571 # update a DynDNS host. They only provide the update url
572 # on the their german subpage.
573 #
574 # http://hilfe.ovh.de/DomainDynHost
575
576 url = "https://www.ovh.com/nic/update"
577
578 def _prepare_request_data(self):
54d3efc8
MT
579 data = DDNSProviderDynDNS._prepare_request_data(self)
580 data.update({
581 "system" : "dyndns",
582 })
583
584 return data
a508bda6
SS
585
586
ef33455e 587class DDNSProviderRegfish(DDNSProvider):
6a11646e
MT
588 handle = "regfish.com"
589 name = "Regfish GmbH"
590 website = "http://www.regfish.com/"
ef33455e
SS
591
592 # A full documentation to the providers api can be found here
593 # but is only available in german.
594 # https://www.regfish.de/domains/dyndns/dokumentation
595
596 url = "https://dyndns.regfish.de/"
597
598 def update(self):
599 data = {
600 "fqdn" : self.hostname,
601 }
602
603 # Check if we update an IPv6 address.
604 address6 = self.get_address("ipv6")
605 if address6:
606 data["ipv6"] = address6
607
608 # Check if we update an IPv4 address.
609 address4 = self.get_address("ipv4")
610 if address4:
611 data["ipv4"] = address4
612
613 # Raise an error if none address is given.
614 if not data.has_key("ipv6") and not data.has_key("ipv4"):
615 raise DDNSConfigurationError
616
617 # Check if a token has been set.
618 if self.token:
619 data["token"] = self.token
620
621 # Raise an error if no token and no useranem and password
622 # are given.
623 elif not self.username and not self.password:
624 raise DDNSConfigurationError(_("No Auth details specified."))
625
626 # HTTP Basic Auth is only allowed if no token is used.
627 if self.token:
628 # Send update to the server.
629 response = self.send_request(self.url, data=data)
630 else:
631 # Send update to the server.
632 response = self.send_request(self.url, username=self.username, password=self.password,
633 data=data)
634
635 # Get the full response message.
636 output = response.read()
637
638 # Handle success messages.
639 if "100" in output or "101" in output:
640 return
641
642 # Handle error codes.
643 if "401" or "402" in output:
644 raise DDNSAuthenticationError
645 elif "408" in output:
646 raise DDNSRequestError(_("Invalid IPv4 address has been sent."))
647 elif "409" in output:
648 raise DDNSRequestError(_("Invalid IPv6 address has been sent."))
649 elif "412" in output:
650 raise DDNSRequestError(_("No valid FQDN was given."))
651 elif "414" in output:
652 raise DDNSInternalServerError
653
654 # If we got here, some other update error happened.
655 raise DDNSUpdateError
656
657
04db1862 658class DDNSProviderSelfhost(DDNSProviderDynDNS):
6a11646e
MT
659 handle = "selfhost.de"
660 name = "Selfhost.de"
661 website = "http://www.selfhost.de/"
f22ab085 662
04db1862 663 url = "https://carol.selfhost.de/nic/update"
f22ab085 664
04db1862
MT
665 def _prepare_request_data(self):
666 data = DDNSProviderDynDNS._prepare_request_data(self)
667 data.update({
668 "hostname" : "1",
669 })
f22ab085 670
04db1862 671 return data
b09b1545
SS
672
673
674class DDNSProviderSPDNS(DDNSProviderDynDNS):
6a11646e
MT
675 handle = "spdns.org"
676 name = "SPDNS"
677 website = "http://spdns.org/"
b09b1545
SS
678
679 # Detailed information about request and response codes are provided
680 # by the vendor. They are using almost the same mechanism and status
681 # codes as dyndns.org so we can inherit all those stuff.
682 #
683 # http://wiki.securepoint.de/index.php/SPDNS_FAQ
684 # http://wiki.securepoint.de/index.php/SPDNS_Update-Tokens
685
686 url = "https://update.spdns.de/nic/update"
4ec90b93
MT
687
688
7488825c 689class DDNSProviderStrato(DDNSProviderDynDNS):
6a11646e
MT
690 handle = "strato.com"
691 name = "Strato AG"
692 website = "http:/www.strato.com/"
7488825c
SS
693
694 # Information about the request and response can be obtained here:
695 # http://www.strato-faq.de/article/671/So-einfach-richten-Sie-DynDNS-f%C3%BCr-Ihre-Domains-ein.html
696
697 url = "https://dyndns.strato.com/nic/update"
698
699
a6183090 700class DDNSProviderTwoDNS(DDNSProviderDynDNS):
6a11646e
MT
701 handle = "twodns.de"
702 name = "TwoDNS"
703 website = "http://www.twodns.de"
a6183090
SS
704
705 # Detailed information about the request can be found here
706 # http://twodns.de/en/faqs
707 # http://twodns.de/en/api
708
709 url = "https://update.twodns.de/update"
710
711 def _prepare_request_data(self):
712 data = {
713 "ip" : self.get_address("ipv4"),
714 "hostname" : self.hostname
715 }
716
717 return data
718
719
03bdd188 720class DDNSProviderUdmedia(DDNSProviderDynDNS):
6a11646e
MT
721 handle = "udmedia.de"
722 name = "Udmedia GmbH"
723 website = "http://www.udmedia.de"
03bdd188
SS
724
725 # Information about the request can be found here
726 # http://www.udmedia.de/faq/content/47/288/de/wie-lege-ich-einen-dyndns_eintrag-an.html
727
728 url = "https://www.udmedia.de/nic/update"
729
730
c8c7ca8f 731class DDNSProviderVariomedia(DDNSProviderDynDNS):
6a11646e
MT
732 handle = "variomedia.de"
733 name = "Variomedia"
734 website = "http://www.variomedia.de/"
735 protocols = ("ipv6", "ipv4",)
c8c7ca8f
SS
736
737 # Detailed information about the request can be found here
738 # https://dyndns.variomedia.de/
739
740 url = "https://dyndns.variomedia.de/nic/update"
741
742 @property
743 def proto(self):
744 return self.get("proto")
745
746 def _prepare_request_data(self):
747 data = {
748 "hostname" : self.hostname,
749 "myip" : self.get_address(self.proto)
750 }
54d3efc8
MT
751
752 return data
98fbe467
SS
753
754
755class DDNSProviderZoneedit(DDNSProvider):
6a11646e
MT
756 handle = "zoneedit.com"
757 name = "Zoneedit"
758 website = "http://www.zoneedit.com"
98fbe467
SS
759
760 # Detailed information about the request and the response codes can be
761 # obtained here:
762 # http://www.zoneedit.com/doc/api/other.html
763 # http://www.zoneedit.com/faq.html
764
765 url = "https://dynamic.zoneedit.com/auth/dynamic.html"
766
767 @property
768 def proto(self):
769 return self.get("proto")
770
771 def update(self):
772 data = {
773 "dnsto" : self.get_address(self.proto),
774 "host" : self.hostname
775 }
776
777 # Send update to the server.
778 response = self.send_request(self.url, username=self.username, password=self.password,
779 data=data)
780
781 # Get the full response message.
782 output = response.read()
783
784 # Handle success messages.
785 if output.startswith("<SUCCESS"):
786 return
787
788 # Handle error codes.
789 if output.startswith("invalid login"):
790 raise DDNSAuthenticationError
791 elif output.startswith("<ERROR CODE=\"704\""):
792 raise DDNSRequestError(_("No valid FQDN was given."))
793 elif output.startswith("<ERROR CODE=\"702\""):
794 raise DDNSInternalServerError
795
796 # If we got here, some other update error happened.
797 raise DDNSUpdateError