Coding style, function naming
authorNico Kaiser <nico@kaiser.me>
Tue, 18 Jun 2013 13:40:21 +0000 (15:40 +0200)
committerNico Kaiser <nico.kaiser@boerse-go.de>
Tue, 18 Jun 2013 13:40:21 +0000 (15:40 +0200)
LICENSE [new file with mode: 0644]
README.md [moved from README.txt with 80% similarity]
htdocs/classes/Dyndns.class.php
htdocs/classes/DyndnsHelper.class.php
htdocs/classes/DyndnsHosts.class.php
htdocs/classes/DyndnsUsers.class.php
htdocs/config.php
htdocs/index.php

diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..eb2aef1
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2007-2013 Nico Kaiser (nico@kaiser.me)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
similarity index 80%
rename from README.txt
rename to README.md
index c1ce6b4..c9006b4 100644 (file)
+++ b/README.md
@@ -1,20 +1,17 @@
-Introduction
-============
+Dyndns: a simple DynDNS server in PHP
+=====================================
 
-This script takes the same parameters as the original members.dyndns.org 
-server does. It can update a BIND DNS server via "nsupdate".
+This script takes the same parameters as the original dyndns.org server does. It can update a BIND DNS server via `nsupdate`.
 
-As it uses the same syntax as the original DynDNS.org servers do, a dynamic DNS server equipped with
-this script can be used with DynDNS compatible clients without having to modify anything on the
-client side.
+As it uses the same syntax as the original DynDNS.org servers do, a dynamic DNS server equipped with this script can be used with DynDNS compatible clients without having to modify anything on the client side.
 
 
 Installation
-============
+------------
 
 To mimic the original DynDNS.org behavior, the Script's URL must be
 
-       http://members.dyndns.org/nic/update
+    http://members.dyndns.org/nic/update
 
 You may have to adjust your own DNS configuration to make "members.dyndns.org" point to your own 
 Server and you Web Servers configuration to make "/nic/update" call the PHP script provided in this 
@@ -24,7 +21,7 @@ package.
 Furthermore, to be able to dynamically update the BIND DNS server, DNS key must be generated with
 the command:
 
-       dnskeygen -n dyndns.example.com -H 512 -h
+    dnskeygen -n dyndns.example.com -H 512 -h
 
 (Where "dyndns.example.com" is the key name)
 The resulting key (look at the "Key:" line in the resulting Kdyndns.example.com.+157+00000.private)
@@ -35,18 +32,18 @@ the BIND configuration (see below).
 The key has to be added to the BIND configuration (named.conf), as well as a DNS zone:
 
 
-key dyndns.example.com. {
-       algorithm HMAC-MD5;
-       secret "bvZ....K5A==";
-};
+    key dyndns.example.com. {
+        algorithm HMAC-MD5;
+        secret "bvZ....K5A==";
+    };
 
-zone "dyndns.example.com" {
-       type master;
-       file "dyndns.example.com.zone";
-       allow-update {
-               key dyndns.example.com.;
-       };
-};
+    zone "dyndns.example.com" {
+        type master;
+        file "dyndns.example.com.zone";
+        allow-update {
+            key dyndns.example.com.;
+        };
+    };
 
 In this case, the zone is also called "dyndns.example.com". The (initial) dyndns.example.com.zone 
 file (located in BIND's cache directory) looks like this:
@@ -71,12 +68,12 @@ The PHP script is called by the DynDNS client, it validates the input and calls
 finally update the DNS with the new data. Its configuration is rather simple, the user database is
 implemented as text file "dyndns.user" with each line containing
 
-       <user>:<password>
+    <user>:<password>
 
 Where <password> is crypt'ed like in Apache's htpasswd files. 
 Hosts are assigned to users in using the file  "dyndns.hosts":
 
-       <host>:<user>(,<user>,<user>,...)
+    <host>:<user>(,<user>,<user>,...)
 
 (So users can update multiple hosts, and a host can be updated by multiple users).
 
@@ -87,7 +84,7 @@ them in your Document root, otherwise every Web user can read them.
 
 
 Implementation
-==============
+--------------
 
 Here you can find details on which capabilities of the DynDNS specification are implemented.
 
@@ -158,6 +155,10 @@ dnserr
 (See http://www.dyndns.com/developers/specs/return.html for more details)
 
 
+Todo
+----
 
-Nico Kaiser
-nico@siriux.net
+* Implement Wildcards
+* Implement NOCHG
+* Implement more features from DynDNS.org
+* Provide Apache templates (for mod_rewrite, etc.)
index 3e46f5c..81e97ab 100644 (file)
 <?php
-/*
- * DynDNS Server Script
- * Copyright (c) 2007 Nico Kaiser
- *  
- * http://siriux.net/
- */
  
 require_once(dirname(__FILE__) . '/DyndnsHelper.class.php');
 require_once(dirname(__FILE__) . '/DyndnsHosts.class.php');
 require_once(dirname(__FILE__) . '/DyndnsUsers.class.php');
 
 /**
- * Simple Dynamic DNS 
+ * Simple Dynamic DNS server.
  * 
  * @package Dyndns
- * @author Nico Kaiser <nico@siriux.net>
- * @version $Revision: 13 $
+ * @author  Nico Kaiser <nico@kaiser.me>
  */
-class Dyndns {
-       
-       /**
+class Dyndns
+{    
+    /**
      * Storage for all configuration variables, set in config.php
-     * @var array 
-     * @access private
+     * @var array
+     */
+    private $config;
+
+    /**
+     * The user currently logged in
+     * @var string
+     */
+    private $user;
+
+    /**
+     * IP the hostnames should point to
+     * @var string
+     */
+    private $myIp;
+
+    /**
+     * Hostnames that should be updated
+     * @var array
      */
-       var $_config;
-       
-       /**
-        * The user logged in 
-        * @var string
-        * @access private
-        */
-       var $_user;
-       
-       /**
-        * IP the hostnames should point to
-        * @var string
-        * @access private
-        */
-       var $_myIp;
-       
-       /**
-        * Hostnames that should be updated
-        * @var array 
-        * @access private
-        */
-       var $_hostnames;
-       
-       /**
-        * Debug buffer
-        * @var string
-        * @access private
-        */ 
-       var $_debugBuffer;
-       
-       
-       function Dyndns() {
-               /* Default config settings */
-               $this->_config = array (
-                       'hostsFile' => 'dyndns.hosts',          /* Location of the hosts database */
-                       'userFile' => 'dyndns.user',            /* Location of the user database */
-                       'debugFile' => 'dyndns.log',            /* Debug file */
-                       'debug' => false,                                       /* Enable debugging */
-                       
-                       'bind.server' => false,
-                       'bind.zone' => '',
-                       'bind.ttl' => 300,
-                       'bind.key' => '',
-               );
-       }
-       
-       /**
-        * Initializes the Dyndns script
-        */
-       function init() {
-               $this->_users = new DyndnsUsers($this->_config['userFile']);
-               $this->_hosts = new DyndnsHosts($this->_config['hostsFile']);
-               
-               $this->_checkHttpMethod();
-               $this->_checkAuthentication();
-               
-               /* Get IP address, fallback to REMOTE_ADDR */
-               $this->_myIp = DyndnsHelper::getMyIp();
-               if (array_key_exists('myip', $_REQUEST)) {
-                       if (DyndnsHelper::checkValidIp($_REQUEST['myip'])) {
-                               $this->_myIp = $_REQUEST['myip'];
-                       } else {
-                               $this->debug('Invalid parameter myip. Using default REMOTE_ADDR');
-                       }
-               }
-               
-               /* Get hostnames to be updated */
-               $this->_hostnames = array ();
-               if (array_key_exists('hostname', $_REQUEST) && ($_REQUEST['hostname'] != '')) {
-                       $this->_hostnames = explode(',', strtolower($_REQUEST['hostname']));
-                       $this->_checkHostnames();
-               } else {
-                       $this->_returnCode('notfqdn');
-               }
-               
-               $this->_updateHosts();
-                               
-               /* Return "good" code as everything seems to be ok now */
-               $this->_returnCode('good');
-       }
-       
-       /**
-        * Store a value in the config table
-        *
-        * @param string $key
-        * @param mixed $value
-        */
-       function setConfig($key, $value) {
-               $this->_config[$key] = $value;
-       }
-       
-       /**
-        * Get a value from the config table
-     *
-        * @return mixed an arbitrary value
-        */
-    function getConfig($key) {
-               return $this->_config[$key];
+    private $hostnames;
+
+    /**
+     * Debug buffer
+     * @var string
+     */ 
+    private $debugBuffer;
+
+    public function __construct()
+    {
+        $this->config = array (
+            'hostsFile' => 'dyndns.hosts',     // Location of the hosts database
+            'userFile' => 'dyndns.user',    // Location of the user database
+            'debugFile' => 'dyndns.log',       // Debug file
+            'debug' => false,               // Enable debugging
+            
+            'bind.server' => false,
+            'bind.zone' => '',
+            'bind.ttl' => 300,
+            'bind.key' => '',
+        );
+    }
+
+    public function init()
+    {
+        $this->users = new DyndnsUsers($this->config['userFile']);
+        $this->hosts = new DyndnsHosts($this->config['hostsFile']);
+        
+        $this->checkHttpMethod();
+        $this->checkAuthentication();
+        
+        // Get IP address, fallback to REMOTE_ADDR
+        $this->myIp = DyndnsHelper::getMyIp();
+        if (array_key_exists('myip', $_REQUEST)) {
+            if (DyndnsHelper::checkValidIp($_REQUEST['myip'])) {
+                $this->myIp = $_REQUEST['myip'];
+            } else {
+                $this->debug('Invalid parameter myip. Using default REMOTE_ADDR');
+            }
+        }
+        
+        // Get hostnames to be updated
+        $this->hostnames = array ();
+        if (array_key_exists('hostname', $_REQUEST) && ($_REQUEST['hostname'] != '')) {
+            $this->hostnames = explode(',', strtolower($_REQUEST['hostname']));
+            $this->checkHostnames();
+        } else {
+            $this->returnCode('notfqdn');
+        }
+        
+        $this->updateHosts();
+                
+        // Return "good" code as everything seems to be ok now
+        $this->returnCode('good');
+    }
+    
+    public function setConfig($key, $value)
+    {
+        $this->config[$key] = $value;
     }
     
-       /**
-        * Checks if the HTTP method is supported. Currently, only GET is supported,
-        * all other methods will result in a "badagent" code.
-        * 
-        * @access private
-        */
-       function _checkHttpMethod() {
-               /* Only HTTP method "GET" is allowed here */
-               if ($_SERVER['REQUEST_METHOD'] != 'GET') {
-                       $this->debug('ERROR: HTTP method ' . $_SERVER['REQUEST_METHOD'] . ' is not allowed.');
-                       $this->_returnCode('badagent', Array ('HTTP/1.0 405 Method Not Allowed'));
-               }
-       }
-       
-       /**
-        * Handles authentication. Requests HTTP authentication and if user/pw is submitted
-        * check if they are valid
-        * 
-        * @access private
-        */ 
-       function _checkAuthentication() {
-               /* Request user/pw if not submitted yet */
-               if (!isset($_SERVER['PHP_AUTH_USER'])) {
-                       $this->debug('No authentication data sent');
-                       $this->_returnCode('badauth', Array (
-                               'WWW-Authenticate: Basic realm="DynDNS API Access"',
-                               'HTTP/1.0 401 Unauthorized')
-                       );
-               }
-               $user = strtolower($_SERVER['PHP_AUTH_USER']);
-               $password = $_SERVER['PHP_AUTH_PW'];
-               if (! $this->_users->checkCredentials($user, $password)) {
-                       $this->_returnCode('badauth', Array ('HTTP/1.0 403 Forbidden'));
-               }
-               $this->_user = $user;
-       }
-       
-       /**
-        * Checks if all hostnames are valid (FQDN) and belong to the user
-        * 
-        * @access private
-        */
-       function _checkHostnames() {
-               foreach ($this->_hostnames as $hostname) {
-                       if (! DyndnsHelper::checkValidHost($hostname)) {
-                               $this->_returnCode('notfqdn');
-                       }
-                       if (! $this->_hosts->checkUserHost($this->_user, $hostname)) {
-                               $this->_returnCode('nohost');
-                       }
-               }
-       }
-       
-       /**
-        * Updates all hosts
-        * 
-        * @param string hostname Hostname
-        * @param string myip IP address
-        */
-       function _updateHosts() {
-               foreach ($this->_hostnames as $hostname) {
-                       if (! $this->_hosts->update($hostname, $this->_myIp) ) {
-                               $this->_returnCode('dnserr');
-                       }
-               }
-               /* Flush host database (write to hosts file) */
-               if (! $this->_hosts->flush()) {
-                       $this->_returnCode('dnserr');
-               }
-       }
-       
-       /**
-        * Returns a "Return code". The program exits after output.
-        * 
-        * @param string code Return code (like "notfqdn")
-        * @param array additionalHeaders HTTP headers to be added
-        * @param string debugMessage Message for the debug log
-        */
-       function _returnCode($code, $additionalHeaders = Array (), $debugMessage = "") {
-               foreach ($additionalHeaders as $header) {
-                       header($header);
-               }
-               $this->debug('Sending return code: ' . $code);
-               echo $code;
-               $this->_shutdown();
-       }
-       
-       /**
-        * Shuts down, closes files, writes debug output, etc.
-        *
-        * @access private
-        */
-       function _shutdown() {
-               /* Write debug buffer */
-               if ( ($this->_debugBuffer != "") && ($this->_config['debug'])) {
-                       if ($fh = @fopen($this->_config['debugFile'], 'a')) {
-                               fwrite($fh, $this->_debugBuffer);
-                               fclose($fh);
-                       }
-               }
-               exit;
-       }
-       
-       /**
-        * Saves a debug message (if debugging is turned on)
-        * 
-        * @param string message Debug message
-        */
-       function debug($message) {
-               $this->_debugBuffer .= date('M j G:i:s') . ' Dyndns: ' . $message . "\n";
-       }
+    public function getConfig($key)
+    {
+        return $this->config[$key];
+    }
+
+    private function checkHttpMethod()
+    {
+        // Only HTTP method "GET" is allowed here
+        if ($_SERVER['REQUEST_METHOD'] != 'GET') {
+            $this->debug('ERROR: HTTP method ' . $_SERVER['REQUEST_METHOD'] . ' is not allowed.');
+            $this->returnCode('badagent', array('HTTP/1.0 405 Method Not Allowed'));
+        }
+    }
+
+    private function checkAuthentication()
+    {
+        // Request user/pw if not submitted yet
+        if (!isset($_SERVER['PHP_AUTH_USER'])) {
+            $this->debug('No authentication data sent');
+            $this->returnCode('badauth', array(
+                'WWW-Authenticate: Basic realm="DynDNS API Access"',
+                'HTTP/1.0 401 Unauthorized')
+            );
+        }
+
+        $user = strtolower($_SERVER['PHP_AUTH_USER']);
+        $password = $_SERVER['PHP_AUTH_PW'];
+        if (! $this->users->checkCredentials($user, $password)) {
+            $this->returnCode('badauth', array('HTTP/1.0 403 Forbidden'));
+        }
+
+        $this->user = $user;
+    }
+
+    private function checkHostnames()
+    {
+        foreach ($this->hostnames as $hostname) {
+               // check if the hostname is valid FQDN
+            if (! DyndnsHelper::checkValidHost($hostname)) {
+                $this->returnCode('notfqdn');
+            }
+
+            // check if the user is allowed to update the hostname
+            if (! $this->hosts->checkUserHost($this->user, $hostname)) {
+                $this->returnCode('nohost');
+            }
+        }
+    }
+
+    private function updateHosts()
+    {
+        foreach ($this->hostnames as $hostname) {
+            if (! $this->hosts->update($hostname, $this->myIp) ) {
+                $this->returnCode('dnserr');
+            }
+        }
+        
+        // Flush host database (write to hosts file)
+        if (! $this->hosts->flush()) {
+            $this->returnCode('dnserr');
+        }
+    }
+
+    private function returnCode($code, $additionalHeaders = array(), $debugMessage = "")
+    {
+        foreach ($additionalHeaders as $header) {
+            header($header);
+        }
+        $this->debug('Sending return code: ' . $code);
+        echo $code;
+        $this->shutdown();
+    }
+
+    private function shutdown()
+    {
+        // Flush debug buffer
+        if (($this->debugBuffer != "") && ($this->config['debug'])) {
+            if ($fh = @fopen($this->config['debugFile'], 'a')) {
+                fwrite($fh, $this->debugBuffer);
+                fclose($fh);
+            }
+        }
+
+        exit;
+    }
+
+    private function debug($message)
+    {
+        $this->debugBuffer .= date('M j G:i:s') . ' Dyndns: ' . $message . "\n";
+    }
 }
-?>
\ No newline at end of file
index b8e915f..fa87048 100644 (file)
@@ -1,79 +1,77 @@
 <?php
-/*
- * DynDNS Server Script
- * Copyright (c) 2007 Nico Kaiser
- *  
- * http://siriux.net/
- */
 
 /**
- * Collection of useful helper functions
+ * Helper functions.
  * 
  * @package Dyndns
- * @author Nico Kaiser <nico@siriux.net>
- * @version $Revision: 13 $
- * @static
+ * @author  Nico Kaiser <nico@kaiser.me>
  */
-class DyndnsHelper {
-       
-       /**
-        * Simple function to check valid IP address
-        *
-        * @param string IP address
-        * @return boolean True if IP is valid
-        */ 
-       function checkValidIp($ip) {
-               if (! eregi("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", $ip)) 
-                       return false;   
-               $tmp = explode(".", $ip);
-               foreach ($tmp as $sub) {
-                       $sub = $sub * 1;
-                       if ($sub < 0 || $sub > 256) return true;
-               }
-               return true;
-       }
-       
-       /**
-        * Simple function to check valid Hostname (FQDN)
-        *
-        * @param string Hostname
-        * @return boolean True if Hostname is valid
-        */ 
-       function checkValidHost($hostname) {
-               return eregi('^[a-z0-9.-]+$', $hostname);
-       }
-       
-       /**
-        * Tries to get the IPv4 of the client
-        *
-        * @param access public
-        * @return string ip 
-        */
-       function getMyIp() {
-               $ip = $_SERVER['REMOTE_ADDR'];
-               /* Some IPv6 Servers add ::ffff: */
-               $ip = preg_replace('/^::ffff:/', '', $ip);
-               return $ip;
-       }
-       
-       /**
-        * Compares if two hostnames are the same, with regard to a wildcard
-        *
-        * @param string host1
-        * @param string host2
-        * @return boolean true or false
-        */
-       function compareHosts($host1, $host2, $wildcard = false) {
-               $a = explode('.', $host1);
-               $b = explode('.', $host2);              
-               if (count($a) != count($b))
-                       return false;
-               for ($i = 0; $i < count($a); $i++) {
-                       if (($wildcard === false) or (($a[$i] != $wildcard) and ($b[$i] != $wildcard)))
-                               if ($a[$i] != $b[$i])
-                                       return false;
-               }
-               return true;
-       }
+class DyndnsHelper
+{    
+    /**
+     * Check valid IP address
+     *
+     * @param string IP address
+     * @return boolean True if IP is valid
+     */ 
+    public static function checkValidIp($ip)
+    {
+        if (! eregi("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", $ip)) 
+            return false;
+
+        $tmp = explode(".", $ip);
+        foreach ($tmp as $sub) {
+            $sub = $sub * 1;
+            if ($sub < 0 || $sub > 256) return true;
+        }
+
+        return true;
+    }
+    
+    /**
+     * Check valid hostname (FQDN)
+     *
+     * @param string Hostname
+     * @return boolean
+     */ 
+    public static function checkValidHost($hostname)
+    {
+        return eregi('^[a-z0-9.-]+$', $hostname);
+    }
+
+    /**
+     * Tries to get the IPv4 of the client
+     *
+     * @return string ip 
+     */
+    public static function getMyIp()
+    {
+        $ip = $_SERVER['REMOTE_ADDR'];
+        $ip = preg_replace('/^::ffff:/', '', $ip); // Some IPv6 Servers add ::ffff:
+        return $ip;
+    }
+
+    /**
+     * Compares if two hostnames are the same, with regard to a wildcard
+     *
+     * @param string host1
+     * @param string host2
+     * @return boolean
+     */
+    public static function compareHosts($host1, $host2, $wildcard = false)
+    {
+        $a = explode('.', $host1);
+        $b = explode('.', $host2);        
+
+        if (count($a) != count($b))
+            return false;
+
+        for ($i = 0; $i < count($a); $i++) {
+            if (($wildcard === false) or (($a[$i] != $wildcard) and ($b[$i] != $wildcard)))
+                if ($a[$i] != $b[$i])
+                    return false;
+        }
+
+        return true;
+    }
 }
-?>
\ No newline at end of file
index 8c1639d..cca9282 100644 (file)
 <?php
-/*
- * DynDNS Server Script
- * Copyright (c) 2007 Nico Kaiser
- *  
- * http://siriux.net/
- */
 
 /**
- * Host database
+ * Host database.
  * 
  * @package Dyndns
- * @author Nico Kaiser <nico@siriux.net>
- * @version $Revision: 13 $
+ * @author  Nico Kaiser <nico@kaiser.me>
  */
-class DyndnsHosts {
-       
-       /**
-        * Filename of the hosts file (dyndns.hosts)
-        * @var string 
-        * @access private
-        */
-       var $_hostsFile;
-       
-       /**
-        * Host/Users array:  'hostname' => array ('user1', 'user2', ...)
-        * @var array 
-        * @access private
-        */
-       var $_hosts;
-       
-       /**
-        * List of updates in the format 'hostname' => 'ip'
-        * @var array
-        * @access
-        */
-       var $_updates;
-       
-       /**
-        * This is true if the status / user files were read
-        * @var boolean
-        * @access private
-        */
-       var $_initialized;
-               
-       
-       function DyndnsHosts($hostsFile) {
-               $this->_hostsFile = $hostsFile;
-               $this->_initialized = false;
-               $this->_updates = array ();
-       }
-       
-       /**
-        * Adds an update to the list
-        */
-       function update($hostname, $ip) {
-               if (! $this->_initialized)
-                       $this->_init();
-               
-               $GLOBALS['dyndns']->debug('Update: '.$hostname . ':'.$ip);
-               $this->_updates[$hostname] = $ip;
-               return true;
-       }
-       
-       /**
-        * Checks if the host belongs to the user 
-        * 
-        * @param string user Username
-        * @param string hostname Hostname
-        * @return boolean TRUE if the host belongs to the user
-        */
-       function checkUserHost($user, $hostname) {
-               if ($hostname == 'members.dyndns.org') {
-                       $GLOBALS['dyndns']->debug('Cannot change members.dyndns.org');
-                       return false;
-               }
-               if (! DyndnsHelper::checkValidHost($hostname)) {
-                       $GLOBALS['dyndns']->debug('Invalid host: ' . $hostname);
-                       return false;
-               }
-               if (! $this->_initialized)
-                       $this->_init();
-               if (is_array($this->_hosts)) {
-                       foreach ($this->_hosts as $line) {
-                               if (preg_match("/^(.*?):(.*)/", $line, $matches)) {
-                                       if (DyndnsHelper::compareHosts($matches[1], $hostname, '*') && 
-                                                   in_array($user, explode(',', strtolower($matches[2])))) {
-                                               return true;
-                                       }
-                               }
-                       }
-               }
-               $GLOBALS['dyndns']->debug('Host '.$hostname.' does not belong to user '.$user);
-               return false;
-       }
-       
-       /**
-        * Write cached changes to the status file 
-        * 
-        * @access public
-        */
-       function flush() {
-               return $this->_updateBind();
-       }
-       
-       /**
-        * Initializes the user and status list from the file 
-        * 
-        * @access private
-        */
-       function _init() {
-               if ($this->_initialized) return;
-               $this->_readHostsFile();
-               if (! is_array($this->_hosts)) {
-                       $this->_hosts = Array ();
-               }
-               $this->_initialized = true;
-       }
-       
-       /**
-        * Reads the contents of $_hostsFile into $_hosts
-        * 
-        * @access private
-        */
-       function _readHostsFile() {
-               $lines = @file($this->_hostsFile);
-               if (is_array($lines)) {
-                       $this->_hosts = $lines;
-               } else {
-                       $GLOBALS['dyndns']->debug('Empty hosts file: "' . $this->hostsFile . '"');
-               }
-       }
-       
-       /**
-        * Sends DNS Updates to BIND server
-        * 
-        * @access private
-        */
-       function _updateBind() {
-               $server = $GLOBALS['dyndns']->getConfig('bind.server');
-               $zone = $GLOBALS['dyndns']->getConfig('bind.zone');
-               $ttl = $GLOBALS['dyndns']->getConfig('bind.ttl') * 1;
-               $key = $GLOBALS['dyndns']->getConfig('bind.key');
-               
-               if (! DyndnsHelper::checkValidHost($server)) {
-                       $GLOBALS['dyndns']->debug('ERROR: Invalid bind.server config value');
-                       return false;
-               }
-               if (! DyndnsHelper::checkValidHost($zone)) {
-                       $GLOBALS['dyndns']->debug('ERROR: Invalid bind.zone config value');
-                       return false;
-               }
-               if (! is_int($ttl)) {
-                       $GLOBALS['dyndns']->debug('Invalid bind.ttl config value. Setting to default 300.');
-                       $ttl = 300;
-               }
-               if ($ttl < 60) {
-                       $GLOBALS['dyndns']->debug('bind.ttl is too low. Setting to default 300.');
-                       $ttl = 300;
-               }
-               if (! eregi('^[a-z0-9.-=/]+$', $key)) {
-                       $GLOBALS['dyndns']->debug('ERROR: Invalid bind.key config value');
-                       return false;
-               }
-               
-               /* Create temp file with nsupdate commands */
-               $tempfile = tempnam('/tmp', 'Dyndns');
-               $fh = @fopen($tempfile, 'w');
-               if (! $fh) {
-                       $GLOBALS['dyndns']->debug('ERROR: Could not open temporary file');
-                       return false;
-               }
-               fwrite($fh, "server $server\n");
-               fwrite($fh, "zone $zone\n");
-               $ttl = $GLOBALS['dyndns']->getConfig('bind.ttl');
-               foreach ($this->_updates as $host => $ip) {
-                       fwrite($fh, "update delete $host A\n");
-                       fwrite($fh, "update add $host $ttl A $ip\n");
-               }
-               fwrite($fh, "send\n");
-               fclose($fh);
-               
-               /* Execute nsupdate */
-               $result = exec('/usr/bin/nsupdate -y ' . $key . ' ' . $tempfile . ' 2>&1');
-               unlink($tempfile);
-               if ($result != '') {
-                       $GLOBALS['dyndns']->debug('ERROR: nsupdate returns: ' . $result);
-                       return false;
-               }
-               
-               return true;
-       }
+class DyndnsHosts
+{    
+    /**
+     * Filename of the hosts file (dyndns.hosts)
+     * @var string
+     */
+    private $hostsFile;
+
+    /**
+     * Host/Users array:  'hostname' => array ('user1', 'user2', ...)
+     * @var array
+     */
+    private $hosts;
+    
+    /**
+     * List of updates in the format 'hostname' => 'ip'
+     * @var array
+     */
+    private $updates;
+    
+    /**
+     * This is true if the status / user files were read
+     * @var boolean
+     */
+    private $initialized;
+
+    /**
+     * Constructor.
+     *
+     * @param string $hostsFile
+     */
+    public function __construct($hostsFile)
+    {
+        $this->hostsFile = $hostsFile;
+        $this->initialized = false;
+        $this->updates = array();
+    }
+
+    /**
+     * Adds an update to the list
+     *
+     * @param string $hostname
+     * @param string $ip
+     */
+    public function update($hostname, $ip)
+    {
+        if (! $this->initialized) {
+            $this->init();
+        }
+        
+        $this->debug('Update: ' . $hostname . ':' . $ip);
+        $this->updates[$hostname] = $ip;
+    }
+
+    /**
+     * Checks if the host belongs to the user 
+     *
+     * @param string $user
+     * @param string $hostname
+     * @return boolean True if the user is allowed to update the host
+     */
+    function checkUserHost($user, $hostname)
+    {
+        if ($hostname === 'members.dyndns.org') {
+            $this->debug('Cannot change members.dyndns.org');
+            return false;
+        }
+
+        if (! DyndnsHelper::checkValidHost($hostname)) {
+            $this->debug('Invalid host: ' . $hostname);
+            return false;
+        }
+
+        if (! $this->initialized) {
+               $this->init();
+        }
+
+        if (is_array($this->hosts)) {
+            foreach ($this->hosts as $line) {
+                if (preg_match("/^(.*?):(.*)/", $line, $matches)) {
+                    if (DyndnsHelper::compareHosts($matches[1], $hostname, '*') && 
+                            in_array($user, explode(',', strtolower($matches[2])))) {
+                        return true;
+                    }
+                }
+            }
+        }
+        $this->debug('Host '.$hostname.' does not belong to user '.$user);
+        return false;
+    }
+    
+    /**
+     * Write cached changes to the status file 
+     */
+    public function flush()
+    {
+        return $this->updateBind();
+    }
+    
+    /**
+     * Initializes the user and status list from the file 
+     * 
+     * @access private
+     */
+    private function init()
+    {
+        if ($this->initialized) return;
+
+        $this->readHostsFile();
+        if (! is_array($this->hosts)) {
+            $this->hosts = array();
+        }
+
+        $this->initialized = true;
+    }
+    
+    function readHostsFile()
+    {
+        $lines = @file($this->hostsFile);
+        if (is_array($lines)) {
+            $this->hosts = $lines;
+        } else {
+            $this->debug('Empty hosts file: "' . $this->hostsFile . '"');
+        }
+    }
+    
+    /**
+     * Sends DNS Updates to BIND server
+     * 
+     * @access private
+     */
+    private function updateBind()
+    {
+        $server = $this->getConfig('bind.server');
+        $zone = $this->getConfig('bind.zone');
+        $ttl = $this->getConfig('bind.ttl') * 1;
+        $key = $this->getConfig('bind.key');
+
+        // sanitiy checks
+        if (! DyndnsHelper::checkValidHost($server)) {
+            $this->debug('ERROR: Invalid bind.server config value');
+            return false;
+        }
+        if (! DyndnsHelper::checkValidHost($zone)) {
+            $this->debug('ERROR: Invalid bind.zone config value');
+            return false;
+        }
+        if (! is_int($ttl)) {
+            $this->debug('Invalid bind.ttl config value. Setting to default 300.');
+            $ttl = 300;
+        }
+        if ($ttl < 60) {
+            $this->debug('bind.ttl is too low. Setting to default 300.');
+            $ttl = 300;
+        }
+        if (! eregi('^[a-z0-9.-=/]+$', $key)) {
+            $this->debug('ERROR: Invalid bind.key config value');
+            return false;
+        }
+        
+        // create temp file with nsupdate commands
+        $tempfile = tempnam('/tmp', 'Dyndns');
+        $fh = @fopen($tempfile, 'w');
+        if (! $fh) {
+            $this->debug('ERROR: Could not open temporary file');
+            return false;
+        }
+        fwrite($fh, "server $server\n");
+        fwrite($fh, "zone $zone\n");
+        $ttl = $this->getConfig('bind.ttl');
+        foreach ($this->updates as $host => $ip) {
+            fwrite($fh, "update delete $host A\n");
+            fwrite($fh, "update add $host $ttl A $ip\n");
+        }
+        fwrite($fh, "send\n");
+        fclose($fh);
+        
+        // Execute nsupdate
+        $result = exec('/usr/bin/nsupdate -y ' . $key . ' ' . $tempfile . ' 2>&1');
+        unlink($tempfile);
+        if ($result != '') {
+            $this->debug('ERROR: nsupdate returns: ' . $result);
+            return false;
+        }
+        
+        return true;
+    }
+
+    private function getConfig($key)
+    {
+       return $GLOBALS['dyndns']->getConfig($key);
+    }
+
+    private function debug($message)
+    {
+       return $GLOBALS['dyndns']->debug($message);
+    }
 }
-?>
\ No newline at end of file
index 62c90f6..49b4321 100644 (file)
@@ -1,60 +1,49 @@
 <?php
-/*
- * DynDNS Server Script
- * Copyright (c) 2007 Nico Kaiser
- *  
- * http://siriux.net/
- */
 
 /**
- * User database
+ * User database.
  * 
  * @package Dyndns
- * @author Nico Kaiser <nico@siriux.net>
- * @version $Revision: 13 $
+ * @author  Nico Kaiser <nico@kaiser.me>
  */
-class DyndnsUsers {
-       
-       /**
-        * Filename of the users file
-        * @var string 
-        * @access private
-        */
-       var $_userFile;
-       
-       
-       function DyndnsUsers($userFile) {
-               $this->_userFile = $userFile;
-       }
-       
-       /**
-        * Checks user credentials
-        *
-        * @param string user 
-        * @param string password
-        * @access private
-        */
-       function checkCredentials($user, $password) {
-               $lines = @file($this->_userFile);
-               if (is_array($lines)) {
-                       foreach ($lines as $line) {
-                               if (preg_match("/^(.*?):(.*)/", $line, $matches)) {
-                                       if (strtolower($matches[1]) == strtolower($user)) {
-                                               $salt = substr($matches[2], 0, 2);                              
-                                               if (crypt($password, $salt) == $matches[2]) {
-                                                       $GLOBALS['dyndns']->debug('Login successful for user ' . $user);
-                                                       return TRUE;
-                                               } else {
-                                                       $GLOBALS['dyndns']->debug('Wrong password for user: ' . $user);
-                                               }
-                                       }
-                               }
-                       }
-               } else {
-                       $GLOBALS['dyndns']->debug('Empty user file: "' . $this->_userFile . '"');
-               }
-               $GLOBALS['dyndns']->debug('Unknown user: ' . $user);
-               return FALSE;
-       }
+class DyndnsUsers
+{
+    private $userFile;
+
+    public function __construct($userFile)
+    {
+        $this->userFile = $userFile;
+    }
+
+    private function checkCredentials($user, $password)
+    {
+        $lines = @file($this->userFile);
+
+        if (is_array($lines)) {
+            foreach ($lines as $line) {
+                if (preg_match("/^(.*?):(.*)/", $line, $matches)) {
+                    if (strtolower($matches[1]) == strtolower($user)) {
+                        $salt = substr($matches[2], 0, 2);                
+                        if (crypt($password, $salt) == $matches[2]) {
+                            $this->debug('Login successful for user ' . $user);
+                            return true;
+                        } else {
+                            $this->debug('Wrong password for user: ' . $user);
+                            return false;
+                        }
+                    }
+                }
+            }
+        } else {
+            $this->debug('Empty user file: "' . $this->userFile . '"');
+        }
+
+        $this->debug('Unknown user: ' . $user);
+        return false;
+    }
+
+    private function debug($message)
+    {
+        $GLOBALS['dyndns']->debug($message); 
+    }
 }
-?>
\ No newline at end of file
index c7205c0..12e6ebd 100644 (file)
@@ -6,30 +6,25 @@ if (!isset($dyndns) || !method_exists($dyndns, 'setConfig')) {
        exit;
 }
 
-
 /* 
  * Location of the hosts database
  */
 $dyndns->setConfig('hostsFile', 'conf/dyndns.hosts');
 
-
 /* 
  * Location of the user database
  */
 $dyndns->setConfig('userFile', 'conf/dyndns.user');
 
-
 /* 
  * Enable debugging?
  */
 $dyndns->setConfig('debug', true);     
 
-
 /* 
  * Debug filename
  */
-$dyndns->setConfig('debugFile', '/tmp/dyndns.log');
-                       
+$dyndns->setConfig('debugFile', '/tmp/dyndns.log');                    
 
 /*
  * Secret Key for BIND nsupdate
@@ -37,23 +32,18 @@ $dyndns->setConfig('debugFile', '/tmp/dyndns.log');
  */
 $dyndns->setConfig('bind.key', 'dyndns.example.com:bvZfFHkl16wNGL/LuEUAqvlBeue9lw7C8GkHnQucN6jpKDMjOu29zFR6LlO5YlpNzYquDBmDSPVddX9SuFIK5A==');
 
-
 /*
  * Address of the BIND server. You can specify any remote DNS server here, 
  * if the server allows you to update data using bind.key
  */
 $dyndns->setConfig('bind.server', 'localhost');
 
-
 /*
  * The BIND zone which retrieves the updates
  */
 $dyndns->setConfig('bind.zone', 'dyndns.example.com');
 
-
 /*
  * Dynamic DNS entries will get this TTL
  */
 $dyndns->setConfig('bind.ttl', '300');
-
-?>
\ No newline at end of file
index 5b60f3f..23691ad 100644 (file)
@@ -1,10 +1,4 @@
 <?php
-/*
- * DynDNS Server Script
- * Copyright (c) 2007 Nico Kaiser
- *  
- * http://siriux.net/
- */
 
 /**
  * This script takes the same parameters as the original members.dyndns.org 
@@ -16,8 +10,7 @@
  * Remember: This script must be run as 
  *     http://members.dyndns.org/nic/update
  * 
- * @author Nico Kaiser <nico@siriux.net>
- * @version $Revision: 13 $
+ * @author  Nico Kaiser <nico@kaiser.me>
  */
 
 error_reporting(E_ALL);
@@ -29,5 +22,3 @@ $dyndns =& $GLOBALS['dyndns'];
 @include(dirname(__FILE__). '/config.php');
 
 $dyndns->init();
-
-?>
\ No newline at end of file