]> git.ipfire.org Git - ddns.git/blame - src/ddns/providers.py
Lightning Wire Labs: Unset unused IP addresses
[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
aa21a4c6 430
a08c1b72 431class DDNSProviderLightningWireLabs(DDNSProvider):
6a11646e
MT
432 handle = "dns.lightningwirelabs.com"
433 name = "Lightning Wire Labs"
434 website = "http://dns.lightningwirelabs.com/"
a08c1b72
SS
435
436 # Information about the format of the HTTPS request is to be found
437 # https://dns.lightningwirelabs.com/knowledge-base/api/ddns
438 url = "https://dns.lightningwirelabs.com/update"
439
5f402f36 440 def update(self):
a08c1b72
SS
441 data = {
442 "hostname" : self.hostname,
e3c70807
MT
443 "address6" : self.get_address("ipv6", "-"),
444 "address4" : self.get_address("ipv4", "-"),
a08c1b72
SS
445 }
446
a08c1b72
SS
447 # Check if a token has been set.
448 if self.token:
449 data["token"] = self.token
450
451 # Check for username and password.
452 elif self.username and self.password:
453 data.update({
454 "username" : self.username,
455 "password" : self.password,
456 })
457
458 # Raise an error if no auth details are given.
459 else:
460 raise DDNSConfigurationError
461
462 # Send update to the server.
cb455540 463 response = self.send_request(self.url, data=data)
a08c1b72
SS
464
465 # Handle success messages.
466 if response.code == 200:
467 return
468
a08c1b72
SS
469 # If we got here, some other update error happened.
470 raise DDNSUpdateError
471
472
d1cd57eb 473class DDNSProviderNamecheap(DDNSProvider):
6a11646e
MT
474 handle = "namecheap.com"
475 name = "Namecheap"
476 website = "http://namecheap.com"
477 protocols = ("ipv4",)
d1cd57eb
SS
478
479 # Information about the format of the HTTP request is to be found
480 # https://www.namecheap.com/support/knowledgebase/article.aspx/9249/0/nc-dynamic-dns-to-dyndns-adapter
481 # https://community.namecheap.com/forums/viewtopic.php?f=6&t=6772
482
483 url = "https://dynamicdns.park-your-domain.com/update"
484
485 def parse_xml(self, document, content):
486 # Send input to the parser.
487 xmldoc = xml.dom.minidom.parseString(document)
488
489 # Get XML elements by the given content.
490 element = xmldoc.getElementsByTagName(content)
491
492 # If no element has been found, we directly can return None.
493 if not element:
494 return None
495
496 # Only get the first child from an element, even there are more than one.
497 firstchild = element[0].firstChild
498
499 # Get the value of the child.
500 value = firstchild.nodeValue
501
502 # Return the value.
503 return value
504
505 def update(self):
506 # Namecheap requires the hostname splitted into a host and domain part.
507 host, domain = self.hostname.split(".", 1)
508
509 data = {
510 "ip" : self.get_address("ipv4"),
511 "password" : self.password,
512 "host" : host,
513 "domain" : domain
514 }
515
516 # Send update to the server.
517 response = self.send_request(self.url, data=data)
518
519 # Get the full response message.
520 output = response.read()
521
522 # Handle success messages.
523 if self.parse_xml(output, "IP") == self.get_address("ipv4"):
524 return
525
526 # Handle error codes.
527 errorcode = self.parse_xml(output, "ResponseNumber")
528
529 if errorcode == "304156":
530 raise DDNSAuthenticationError
531 elif errorcode == "316153":
532 raise DDNSRequestError(_("Domain not found."))
533 elif errorcode == "316154":
534 raise DDNSRequestError(_("Domain not active."))
535 elif errorcode in ("380098", "380099"):
536 raise DDNSInternalServerError
537
538 # If we got here, some other update error happened.
539 raise DDNSUpdateError
540
541
88f39629 542class DDNSProviderNOIP(DDNSProviderDynDNS):
6a11646e
MT
543 handle = "no-ip.com"
544 name = "No-IP"
545 website = "http://www.no-ip.com/"
f22ab085
MT
546
547 # Information about the format of the HTTP request is to be found
548 # here: http://www.no-ip.com/integrate/request and
549 # here: http://www.no-ip.com/integrate/response
550
88f39629 551 url = "http://dynupdate.no-ip.com/nic/update"
2de06f59 552
88f39629 553 def _prepare_request_data(self):
2de06f59
MT
554 data = {
555 "hostname" : self.hostname,
f22ab085
MT
556 "address" : self.get_address("ipv4"),
557 }
558
88f39629 559 return data
f22ab085
MT
560
561
a508bda6 562class DDNSProviderOVH(DDNSProviderDynDNS):
6a11646e
MT
563 handle = "ovh.com"
564 name = "OVH"
565 website = "http://www.ovh.com/"
a508bda6
SS
566
567 # OVH only provides very limited information about how to
568 # update a DynDNS host. They only provide the update url
569 # on the their german subpage.
570 #
571 # http://hilfe.ovh.de/DomainDynHost
572
573 url = "https://www.ovh.com/nic/update"
574
575 def _prepare_request_data(self):
54d3efc8
MT
576 data = DDNSProviderDynDNS._prepare_request_data(self)
577 data.update({
578 "system" : "dyndns",
579 })
580
581 return data
a508bda6
SS
582
583
ef33455e 584class DDNSProviderRegfish(DDNSProvider):
6a11646e
MT
585 handle = "regfish.com"
586 name = "Regfish GmbH"
587 website = "http://www.regfish.com/"
ef33455e
SS
588
589 # A full documentation to the providers api can be found here
590 # but is only available in german.
591 # https://www.regfish.de/domains/dyndns/dokumentation
592
593 url = "https://dyndns.regfish.de/"
594
595 def update(self):
596 data = {
597 "fqdn" : self.hostname,
598 }
599
600 # Check if we update an IPv6 address.
601 address6 = self.get_address("ipv6")
602 if address6:
603 data["ipv6"] = address6
604
605 # Check if we update an IPv4 address.
606 address4 = self.get_address("ipv4")
607 if address4:
608 data["ipv4"] = address4
609
610 # Raise an error if none address is given.
611 if not data.has_key("ipv6") and not data.has_key("ipv4"):
612 raise DDNSConfigurationError
613
614 # Check if a token has been set.
615 if self.token:
616 data["token"] = self.token
617
618 # Raise an error if no token and no useranem and password
619 # are given.
620 elif not self.username and not self.password:
621 raise DDNSConfigurationError(_("No Auth details specified."))
622
623 # HTTP Basic Auth is only allowed if no token is used.
624 if self.token:
625 # Send update to the server.
626 response = self.send_request(self.url, data=data)
627 else:
628 # Send update to the server.
629 response = self.send_request(self.url, username=self.username, password=self.password,
630 data=data)
631
632 # Get the full response message.
633 output = response.read()
634
635 # Handle success messages.
636 if "100" in output or "101" in output:
637 return
638
639 # Handle error codes.
640 if "401" or "402" in output:
641 raise DDNSAuthenticationError
642 elif "408" in output:
643 raise DDNSRequestError(_("Invalid IPv4 address has been sent."))
644 elif "409" in output:
645 raise DDNSRequestError(_("Invalid IPv6 address has been sent."))
646 elif "412" in output:
647 raise DDNSRequestError(_("No valid FQDN was given."))
648 elif "414" in output:
649 raise DDNSInternalServerError
650
651 # If we got here, some other update error happened.
652 raise DDNSUpdateError
653
654
04db1862 655class DDNSProviderSelfhost(DDNSProviderDynDNS):
6a11646e
MT
656 handle = "selfhost.de"
657 name = "Selfhost.de"
658 website = "http://www.selfhost.de/"
f22ab085 659
04db1862 660 url = "https://carol.selfhost.de/nic/update"
f22ab085 661
04db1862
MT
662 def _prepare_request_data(self):
663 data = DDNSProviderDynDNS._prepare_request_data(self)
664 data.update({
665 "hostname" : "1",
666 })
f22ab085 667
04db1862 668 return data
b09b1545
SS
669
670
671class DDNSProviderSPDNS(DDNSProviderDynDNS):
6a11646e
MT
672 handle = "spdns.org"
673 name = "SPDNS"
674 website = "http://spdns.org/"
b09b1545
SS
675
676 # Detailed information about request and response codes are provided
677 # by the vendor. They are using almost the same mechanism and status
678 # codes as dyndns.org so we can inherit all those stuff.
679 #
680 # http://wiki.securepoint.de/index.php/SPDNS_FAQ
681 # http://wiki.securepoint.de/index.php/SPDNS_Update-Tokens
682
683 url = "https://update.spdns.de/nic/update"
4ec90b93
MT
684
685
7488825c 686class DDNSProviderStrato(DDNSProviderDynDNS):
6a11646e
MT
687 handle = "strato.com"
688 name = "Strato AG"
689 website = "http:/www.strato.com/"
7488825c
SS
690
691 # Information about the request and response can be obtained here:
692 # http://www.strato-faq.de/article/671/So-einfach-richten-Sie-DynDNS-f%C3%BCr-Ihre-Domains-ein.html
693
694 url = "https://dyndns.strato.com/nic/update"
695
696
a6183090 697class DDNSProviderTwoDNS(DDNSProviderDynDNS):
6a11646e
MT
698 handle = "twodns.de"
699 name = "TwoDNS"
700 website = "http://www.twodns.de"
a6183090
SS
701
702 # Detailed information about the request can be found here
703 # http://twodns.de/en/faqs
704 # http://twodns.de/en/api
705
706 url = "https://update.twodns.de/update"
707
708 def _prepare_request_data(self):
709 data = {
710 "ip" : self.get_address("ipv4"),
711 "hostname" : self.hostname
712 }
713
714 return data
715
716
03bdd188 717class DDNSProviderUdmedia(DDNSProviderDynDNS):
6a11646e
MT
718 handle = "udmedia.de"
719 name = "Udmedia GmbH"
720 website = "http://www.udmedia.de"
03bdd188
SS
721
722 # Information about the request can be found here
723 # http://www.udmedia.de/faq/content/47/288/de/wie-lege-ich-einen-dyndns_eintrag-an.html
724
725 url = "https://www.udmedia.de/nic/update"
726
727
c8c7ca8f 728class DDNSProviderVariomedia(DDNSProviderDynDNS):
6a11646e
MT
729 handle = "variomedia.de"
730 name = "Variomedia"
731 website = "http://www.variomedia.de/"
732 protocols = ("ipv6", "ipv4",)
c8c7ca8f
SS
733
734 # Detailed information about the request can be found here
735 # https://dyndns.variomedia.de/
736
737 url = "https://dyndns.variomedia.de/nic/update"
738
739 @property
740 def proto(self):
741 return self.get("proto")
742
743 def _prepare_request_data(self):
744 data = {
745 "hostname" : self.hostname,
746 "myip" : self.get_address(self.proto)
747 }
54d3efc8
MT
748
749 return data
98fbe467
SS
750
751
752class DDNSProviderZoneedit(DDNSProvider):
6a11646e
MT
753 handle = "zoneedit.com"
754 name = "Zoneedit"
755 website = "http://www.zoneedit.com"
98fbe467
SS
756
757 # Detailed information about the request and the response codes can be
758 # obtained here:
759 # http://www.zoneedit.com/doc/api/other.html
760 # http://www.zoneedit.com/faq.html
761
762 url = "https://dynamic.zoneedit.com/auth/dynamic.html"
763
764 @property
765 def proto(self):
766 return self.get("proto")
767
768 def update(self):
769 data = {
770 "dnsto" : self.get_address(self.proto),
771 "host" : self.hostname
772 }
773
774 # Send update to the server.
775 response = self.send_request(self.url, username=self.username, password=self.password,
776 data=data)
777
778 # Get the full response message.
779 output = response.read()
780
781 # Handle success messages.
782 if output.startswith("<SUCCESS"):
783 return
784
785 # Handle error codes.
786 if output.startswith("invalid login"):
787 raise DDNSAuthenticationError
788 elif output.startswith("<ERROR CODE=\"704\""):
789 raise DDNSRequestError(_("No valid FQDN was given."))
790 elif output.startswith("<ERROR CODE=\"702\""):
791 raise DDNSInternalServerError
792
793 # If we got here, some other update error happened.
794 raise DDNSUpdateError