+ # Get the full response message.
+ output = response.read()
+
+ # Handle success messages.
+ if self.get_xml_tag_value(output, "IP") == self.get_address("ipv4"):
+ return
+
+ # Handle error codes.
+ errorcode = self.get_xml_tag_value(output, "ResponseNumber")
+
+ if errorcode == "304156":
+ raise DDNSAuthenticationError
+ elif errorcode == "316153":
+ raise DDNSRequestError(_("Domain not found."))
+ elif errorcode == "316154":
+ raise DDNSRequestError(_("Domain not active."))
+ elif errorcode in ("380098", "380099"):
+ raise DDNSInternalServerError
+
+ # If we got here, some other update error happened.
+ raise DDNSUpdateError
+
+
+class DDNSProviderNOIP(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "no-ip.com"
+ name = "No-IP"
+ website = "http://www.no-ip.com/"
+ protocols = ("ipv4",)
+
+ # Information about the format of the HTTP request is to be found
+ # here: http://www.no-ip.com/integrate/request and
+ # here: http://www.no-ip.com/integrate/response
+
+ url = "http://dynupdate.no-ip.com/nic/update"
+
+ def _prepare_request_data(self):
+ data = {
+ "hostname" : self.hostname,
+ "address" : self.get_address("ipv4"),
+ }
+
+ return data
+
+
+class DDNSProviderNsupdateINFO(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "nsupdate.info"
+ name = "nsupdate.info"
+ website = "http://www.nsupdate.info/"
+ protocols = ("ipv6", "ipv4",)
+
+ # Information about the format of the HTTP request can be found
+ # after login on the provider user intrface and here:
+ # http://nsupdateinfo.readthedocs.org/en/latest/user.html
+
+ # Nsupdate.info uses the hostname as user part for the HTTP basic auth,
+ # and for the password a so called secret.
+ @property
+ def username(self):
+ return self.get("hostname")
+
+ @property
+ def password(self):
+ return self.get("secret")
+
+ @property
+ def proto(self):
+ return self.get("proto")
+
+ @property
+ def url(self):
+ # The update URL is different by the used protocol.
+ if self.proto == "ipv4":
+ return "https://ipv4.nsupdate.info/nic/update"
+ elif self.proto == "ipv6":
+ return "https://ipv6.nsupdate.info/nic/update"
+ else:
+ raise DDNSUpdateError(_("Invalid protocol has been given"))
+
+ def _prepare_request_data(self):
+ data = {
+ "myip" : self.get_address(self.proto),
+ }
+
+ return data
+
+
+class DDNSProviderOpenDNS(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "opendns.com"
+ name = "OpenDNS"
+ website = "http://www.opendns.com"
+
+ # Detailed information about the update request and possible
+ # response codes can be obtained from here:
+ # https://support.opendns.com/entries/23891440
+
+ url = "https://updates.opendns.com/nic/update"
+
+ @property
+ def proto(self):
+ return self.get("proto")
+
+ def _prepare_request_data(self):
+ data = {
+ "hostname" : self.hostname,
+ "myip" : self.get_address(self.proto)
+ }
+
+ return data
+
+
+class DDNSProviderOVH(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "ovh.com"
+ name = "OVH"
+ website = "http://www.ovh.com/"
+ protocols = ("ipv4",)
+
+ # OVH only provides very limited information about how to
+ # update a DynDNS host. They only provide the update url
+ # on the their german subpage.
+ #
+ # http://hilfe.ovh.de/DomainDynHost
+
+ url = "https://www.ovh.com/nic/update"
+
+ def _prepare_request_data(self):
+ data = DDNSProtocolDynDNS2._prepare_request_data(self)
+ data.update({
+ "system" : "dyndns",
+ })
+
+ return data
+
+
+class DDNSProviderRegfish(DDNSProvider):
+ handle = "regfish.com"
+ name = "Regfish GmbH"
+ website = "http://www.regfish.com/"
+
+ # A full documentation to the providers api can be found here
+ # but is only available in german.
+ # https://www.regfish.de/domains/dyndns/dokumentation
+
+ url = "https://dyndns.regfish.de/"
+
+ def update(self):
+ data = {
+ "fqdn" : self.hostname,
+ }
+
+ # Check if we update an IPv6 address.
+ address6 = self.get_address("ipv6")
+ if address6:
+ data["ipv6"] = address6
+
+ # Check if we update an IPv4 address.
+ address4 = self.get_address("ipv4")
+ if address4:
+ data["ipv4"] = address4
+
+ # Raise an error if none address is given.
+ if not data.has_key("ipv6") and not data.has_key("ipv4"):
+ raise DDNSConfigurationError
+
+ # Check if a token has been set.
+ if self.token:
+ data["token"] = self.token
+
+ # Raise an error if no token and no useranem and password
+ # are given.
+ elif not self.username and not self.password:
+ raise DDNSConfigurationError(_("No Auth details specified."))
+
+ # HTTP Basic Auth is only allowed if no token is used.
+ if self.token:
+ # Send update to the server.
+ response = self.send_request(self.url, data=data)
+ else:
+ # Send update to the server.
+ response = self.send_request(self.url, username=self.username, password=self.password,
+ data=data)
+
+ # Get the full response message.
+ output = response.read()
+
+ # Handle success messages.
+ if "100" in output or "101" in output:
+ return
+
+ # Handle error codes.
+ if "401" or "402" in output:
+ raise DDNSAuthenticationError
+ elif "408" in output:
+ raise DDNSRequestError(_("Invalid IPv4 address has been sent."))
+ elif "409" in output:
+ raise DDNSRequestError(_("Invalid IPv6 address has been sent."))
+ elif "412" in output:
+ raise DDNSRequestError(_("No valid FQDN was given."))
+ elif "414" in output:
+ raise DDNSInternalServerError
+
+ # If we got here, some other update error happened.
+ raise DDNSUpdateError
+
+
+class DDNSProviderSelfhost(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "selfhost.de"
+ name = "Selfhost.de"
+ website = "http://www.selfhost.de/"
+ protocols = ("ipv4",)
+
+ url = "https://carol.selfhost.de/nic/update"
+
+ def _prepare_request_data(self):
+ data = DDNSProviderDynDNS._prepare_request_data(self)
+ data.update({
+ "hostname" : "1",
+ })
+
+ return data
+
+
+class DDNSProviderSPDNS(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "spdns.org"
+ name = "SPDNS"
+ website = "http://spdns.org/"
+ protocols = ("ipv4",)
+
+ # Detailed information about request and response codes are provided
+ # by the vendor. They are using almost the same mechanism and status
+ # codes as dyndns.org so we can inherit all those stuff.
+ #
+ # http://wiki.securepoint.de/index.php/SPDNS_FAQ
+ # http://wiki.securepoint.de/index.php/SPDNS_Update-Tokens
+
+ url = "https://update.spdns.de/nic/update"
+
+
+class DDNSProviderStrato(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "strato.com"
+ name = "Strato AG"
+ website = "http:/www.strato.com/"
+ protocols = ("ipv4",)
+
+ # Information about the request and response can be obtained here:
+ # http://www.strato-faq.de/article/671/So-einfach-richten-Sie-DynDNS-f%C3%BCr-Ihre-Domains-ein.html
+
+ url = "https://dyndns.strato.com/nic/update"
+
+
+class DDNSProviderTwoDNS(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "twodns.de"
+ name = "TwoDNS"
+ website = "http://www.twodns.de"
+ protocols = ("ipv4",)
+
+ # Detailed information about the request can be found here
+ # http://twodns.de/en/faqs
+ # http://twodns.de/en/api
+
+ url = "https://update.twodns.de/update"
+
+ def _prepare_request_data(self):
+ data = {
+ "ip" : self.get_address("ipv4"),
+ "hostname" : self.hostname
+ }
+
+ return data
+
+
+class DDNSProviderUdmedia(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "udmedia.de"
+ name = "Udmedia GmbH"
+ website = "http://www.udmedia.de"
+ protocols = ("ipv4",)
+
+ # Information about the request can be found here
+ # http://www.udmedia.de/faq/content/47/288/de/wie-lege-ich-einen-dyndns_eintrag-an.html
+
+ url = "https://www.udmedia.de/nic/update"
+
+
+class DDNSProviderVariomedia(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "variomedia.de"
+ name = "Variomedia"
+ website = "http://www.variomedia.de/"
+ protocols = ("ipv6", "ipv4",)
+
+ # Detailed information about the request can be found here
+ # https://dyndns.variomedia.de/
+
+ url = "https://dyndns.variomedia.de/nic/update"
+
+ @property
+ def proto(self):
+ return self.get("proto")
+
+ def _prepare_request_data(self):
+ data = {
+ "hostname" : self.hostname,
+ "myip" : self.get_address(self.proto)
+ }
+
+ return data
+
+
+class DDNSProviderZoneedit(DDNSProtocolDynDNS2, DDNSProvider):
+ handle = "zoneedit.com"
+ name = "Zoneedit"
+ website = "http://www.zoneedit.com"
+ protocols = ("ipv4",)
+
+ # Detailed information about the request and the response codes can be
+ # obtained here:
+ # http://www.zoneedit.com/doc/api/other.html
+ # http://www.zoneedit.com/faq.html
+
+ url = "https://dynamic.zoneedit.com/auth/dynamic.html"
+
+ @property
+ def proto(self):
+ return self.get("proto")
+
+ def update(self):
+ data = {
+ "dnsto" : self.get_address(self.proto),
+ "host" : self.hostname
+ }
+
+ # Send update to the server.
+ response = self.send_request(self.url, username=self.username, password=self.password,
+ data=data)
+
+ # Get the full response message.
+ output = response.read()
+
+ # Handle success messages.
+ if output.startswith("<SUCCESS"):
+ return
+
+ # Handle error codes.
+ if output.startswith("invalid login"):
+ raise DDNSAuthenticationError
+ elif output.startswith("<ERROR CODE=\"704\""):
+ raise DDNSRequestError(_("No valid FQDN was given."))
+ elif output.startswith("<ERROR CODE=\"702\""):
+ raise DDNSInternalServerError
+
+ # If we got here, some other update error happened.
+ raise DDNSUpdateError