Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    My attempt to add a Dynimac DNS status widget

    Scheduled Pinned Locked Moved webGUI
    9 Posts 3 Posters 4.5k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • stan-qazS
      stan-qaz
      last edited by

      I'm just getting started with pfSense and noticed there was no widget for showing the dynamic DNS update status and thought I'd give creating one a try. The Wiki got me started and I cribbed almost all the code from the regular dynamic DNS settings page.

      Mostly what I did was delete lines that weren't needed for a status widget and copy/edit the .inc file. I also removed the description column to reduce the width and added a column header to the interface column. Now that I have it working I'd appreciate it if someone with a bit more pfSense knowledge looked at it and see if I've made a mess or if there is anything that could be done to remove any unused lines that I missed. Also I'm not sure if what I did for the copyright section is correct.

      I'm unfamiliar with the forum here but I'm attempting to attach a screenshot of the widget, it doesn't show up in the preview but hopefully it will be there when I finally post this.

      Once this is in acceptable shape I'd like to figure out how to submit it for inclusion in an upcoming release of pfSense if that seems like a good idea to the developers.

      File: /usr/local/www/widgets/include/dyn_dns_status.inc

      
      //set variable for custom title
      $dyn_dns_status_title = "Dyn DNS Status";
      $dyn_dns_status_title_link = "services_dyndns.php";
      
      ?>
      

      File: /usr/local/www/widgets/widgets/dyn_dns_status.widget.php

      /*
          Original status page code from: services_dyndns.php
          Copyright (C) 2008 Ermal Lu\xe7i
          Edits to convert it to a widget: dyn_dns_status.php
          Copyright (C) 2013 Stanley P. Miller \ stan-qaz
          All rights reserved.
      
          Redistribution and use in source and binary forms, with or without
          modification, are permitted provided that the following conditions are met:
      
          1\. Redistributions of source code must retain the above copyright notice,
             this list of conditions and the following disclaimer.
      
          2\. Redistributions in binary form must reproduce the above copyright
             notice, this list of conditions and the following disclaimer in the
             documentation and/or other materials provided with the distribution.
      
          THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
          INClUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
          AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
          AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
          OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
          SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
          INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
          CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
          ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
          POSSIBILITY OF SUCH DAMAGE.
      */
      /*
      	pfSense_BUILDER_BINARIES:	/usr/bin/host	
      	pfSense_MODULE:	dyndns
      */
      
      /* added the dyn_dns_status.inc file to the .inc directory, 
      copied from dyn_dns_status.inc and edited it to work with this file */
      require_once("/usr/local/www/widgets/include/dyn_dns_status.inc");
      
      if (!is_array($config['dyndnses']['dyndns']))
      	$config['dyndnses']['dyndns'] = array();
      
      $a_dyndns = &$config['dyndnses']['dyndns'];
      
      function dyndnsCheckIP($int) {
      
      	$ip_address = get_interface_ip($int);
      	if (is_private_ip($ip_address)) {
      		$hosttocheck = "checkip.dyndns.org";
      		$checkip = gethostbyname($hosttocheck);
      		$ip_ch = curl_init("http://{$checkip}");
      		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
      		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
      		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
      		$ip_result_page = curl_exec($ip_ch);
      		curl_close($ip_ch);
      		$ip_result_decoded = urldecode($ip_result_page);
      		preg_match('=Current IP Address: (.*)=siU', $ip_result_decoded, $matches);
      		$ip_address = trim($matches[1]);
      	}
      
      	return $ip_address;
      }
      ?>
      
      | 
                       |
      |  |  |  |  |		
      | 
      		  	  		foreach ($iflist as $if => $ifdesc):
      				if ($dyndns['interface'] == $if): ?>
      
      		   | 
      				  					$types = explode(",", "DNS-O-Matic, DynDNS (dynamic),DynDNS (static),DynDNS (custom),DHS,DyNS,easyDNS,No-IP,ODS.org,ZoneEdit,Loopia,freeDNS, DNSexit, OpenDNS, Namecheap, HE.net");
      					$vals = explode(" ", "dnsomatic dyndns dyndns-static dyndns-custom dhs dyns easydns noip ods zoneedit loopia freedns dnsexit opendns namecheap he-net");
      					$j = 0; for ($j = 0; $j < count($vals); $j++) 
                            			if ($vals[$j] == $dyndns['type']) { 
                            				echo htmlspecialchars($types[$j]);
      							break;
      					}
      				?>
                         | 
      
                         | 
      							$filename = "{$g['conf_path']}/dyndns_{$if}{$dyndns['type']}" . escapeshellarg($dyndns['host']) . ".cache";
      				$ipaddr = dyndnsCheckIP($if);
      				if(file_exists($filename)) {
      					$cached_ip_s = split(":", file_get_contents($filename));
      					$cached_ip = $cached_ip_s[0];
      					if($ipaddr <> $cached_ip) 
      						echo "";
      					else 
      						echo "";
      						echo htmlspecialchars($cached_ip);
      						echo "";
      				} else {
      					echo "N/A";
      				}
      			?>  |		
      
      

      Thanks for looking at this,
      Stan
      dyn-dns-status-widget.png
      dyn-dns-status-widget.png_thumb

      1 Reply Last reply Reply Quote 0
      • B
        bardelot
        last edited by

        @stan-qaz:

        Once this is in acceptable shape I'd like to figure out how to submit it for inclusion in an upcoming release of pfSense if that seems like a good idea to the developers.

        The best way to have your changes included is to use GitHub. This [1] is the link for the main repository that also contains the files related to the web interface (e.g. widgets). To use GitHub you have to get somehow familiar with Git [2] (a version control system). But don't worry GitHub provides helpful documentation for beginners and examples e.g. how to make a copy of an existing repository [3] and contribute your changes [4].

        [1] https://github.com/bsdperimeter/pfsense/
        [2] http://git-scm.com/
        [3] https://help.github.com/articles/fork-a-repo
        [4] https://help.github.com/articles/using-pull-requests

        1 Reply Last reply Reply Quote 0
        • stan-qazS
          stan-qaz
          last edited by

          I'm going to have to learn Git for some other stuff I"m doing so that isn't a problem but I'm completely clueless about php and pfSense so I'd love some feedback on what I did.

          1 Reply Last reply Reply Quote 0
          • B
            bardelot
            last edited by

            I guess you did quite good for your first attempt with PHP. There are a few minor issues in the HTML code such as the "body" and also an open "table"  tag that shouldn't be there. In terms of PHP you should add the required includes so that the widget does not depend on any other code loading them.

            $nocsrf = true;
            
            require_once("guiconfig.inc");
            require_once("pfsense-utils.inc");
            require_once("functions.inc");
            

            There are also some indentations that could be improved such as both lines after "echo "";", to make clear that they are not part of the else clause. The dyndnsCheckIP function call can be moved into the "file_exists" if clause as it is only used in that context. Also there is a "$j = 0;" before the for loop that is not needed.

            Other than that you could make use of some existing functions such as "convert_real_interface_to_friendly_descr" instead of doing that manually. It could even make sense to create a "convert_dyndns_type_to_friendly_descr" function that is stored in an include file, otherwise the dyndns types always have to be updated in two places when changing them.

            function convert_dyndns_type_to_friendly_descr($dyndnstype) {
            	$types = explode(",", "DNS-O-Matic,DynDNS (dynamic),DynDNS (static),DynDNS (custom),DHS,DyNS,easyDNS,No-IP,ODS.org,ZoneEdit,Loopia,freeDNS,DNSexit,OpenDNS,Namecheap,HE.net,HE.net Tunnelbroker,SelfHost,Route 53,Custom");
            	$vals = explode(" ", "dnsomatic dyndns dyndns-static dyndns-custom dhs dyns easydns noip ods zoneedit loopia freedns dnsexit opendns namecheap he-net he-net-tunnelbroker selfhost route53 custom");
            	$key = array_search($dyndnstype, $vals);
            	return (is_int($key)) ? $types[$key] : "";
            }
            

            I guess most of those changes could also be applied to the original code.

            1 Reply Last reply Reply Quote 0
            • stan-qazS
              stan-qaz
              last edited by

              Reading about Git tonight, I'll give a shot at getting your suggestions in there and submit it. Thanks!

              For newbies it would be nice to have a widget template, maybe in the wiki widget section, that included the mandatory bits and a short "edit this" section that put up a "Hello World" type widget if you did a copy/paste to a running pfSense system.

              1 Reply Last reply Reply Quote 0
              • stan-qazS
                stan-qaz
                last edited by

                I went through and tried to clean things up a bit in line with bardelot's suggestions but I passed on trying to make the change to add the function. As far as I can tell this edited version works the same as the original I submitted so hopefully I didn't break anything in the process.

                /*
                    Original status page code from: services_dyndns.php
                    Copyright (C) 2008 Ermal Lu\xe7i
                    Edits to convert it to a widget: dyn_dns_status.php
                    Copyright (C) 2013 Stanley P. Miller \ stan-qaz
                    All rights reserved.
                
                    Redistribution and use in source and binary forms, with or without
                    modification, are permitted provided that the following conditions are met:
                
                    1\. Redistributions of source code must retain the above copyright notice,
                       this list of conditions and the following disclaimer.
                
                    2\. Redistributions in binary form must reproduce the above copyright
                       notice, this list of conditions and the following disclaimer in the
                       documentation and/or other materials provided with the distribution.
                
                    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                    INClUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
                    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
                    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                    POSSIBILITY OF SUCH DAMAGE.
                */
                /*
                	pfSense_BUILDER_BINARIES:	/usr/bin/host	
                	pfSense_MODULE:	dyndns
                */
                
                $nocsrf = true;
                
                require_once("guiconfig.inc");
                require_once("pfsense-utils.inc");
                require_once("functions.inc");
                
                /* added the dyn_dns_status.inc file to the .inc directory, 
                copied from dyn_dns_status.inc and edited it to work with this file */
                
                require_once("/usr/local/www/widgets/include/dyn_dns_status.inc");
                
                if (!is_array($config['dyndnses']['dyndns']))
                	$config['dyndnses']['dyndns'] = array();
                
                $a_dyndns = &$config['dyndnses']['dyndns'];
                
                function dyndnsCheckIP($int) {
                
                  $ip_address = get_interface_ip($int);
                  if (is_private_ip($ip_address)) {
                    $hosttocheck = "checkip.dyndns.org";
                    $checkip = gethostbyname($hosttocheck);
                    $ip_ch = curl_init("http://{$checkip}");
                    curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
                    curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
                    $ip_result_page = curl_exec($ip_ch);
                    curl_close($ip_ch);
                    $ip_result_decoded = urldecode($ip_result_page);
                    preg_match('=Current IP Address: (.*)=siU', $ip_result_decoded, $matches);
                    $ip_address = trim($matches[1]);
                  }
                  return $ip_address;
                }
                ?>
                
                | 
                       |
                |  |  |  |  |
                | 
                                          foreach ($iflist as $if => $ifdesc):
                                if ($dyndns['interface'] == $if): ?>
                
                           | 
                                          $types = explode(",", "DNS-O-Matic, DynDNS (dynamic),DynDNS (static),DynDNS (custom),DHS,DyNS,easyDNS,No-IP,ODS.org,ZoneEdit,Loopia,freeDNS, DNSexit, OpenDNS, Namecheap, HE.net");
                              $vals = explode(" ", "dnsomatic dyndns dyndns-static dyndns-custom dhs dyns easydns noip ods zoneedit loopia freedns dnsexit opendns namecheap he-net");
                              for ($j = 0; $j < count($vals); $j++) 
                              if ($vals[$j] == $dyndns['type']) { 
                                echo htmlspecialchars($types[$j]);
                                break;
                                }
                            ?>
                           | 
                
                           | 
                                          $filename = "{$g['conf_path']}/dyndns_{$if}{$dyndns['type']}" . escapeshellarg($dyndns['host']) . ".cache";
                              $ipaddr = dyndnsCheckIP($if);
                              if(file_exists($filename)) {
                                $cached_ip_s = split(":", file_get_contents($filename));
                                $cached_ip = $cached_ip_s[0];
                                if($ipaddr <> $cached_ip) echo "";
                                  else echo "";
                                echo htmlspecialchars($cached_ip);
                                echo "";
                              } else echo "N/A";
                            ?>  |
                
                

                My next project will be getting this into git.

                Thanks again for the help.

                1 Reply Last reply Reply Quote 0
                • stan-qazS
                  stan-qaz
                  last edited by

                  I think I got it into the git repository: https://github.com/bsdperimeter/pfsense/pull/413

                  That wasn't too painful!

                  1 Reply Last reply Reply Quote 0
                  • johnpozJ
                    johnpoz LAYER 8 Global Moderator
                    last edited by

                    Hey I just added this to my 2.1 install - but not showing the cached IP, that does show up in the dnydns service area

                    I posted the issue in the 2.1 thread - maybe that is not the correct location for this issue?

                    My thread is here
                    http://forum.pfsense.org/index.php/topic,58867.0.html

                    An intelligent man is sometimes forced to be drunk to spend time with his fools
                    If you get confused: Listen to the Music Play
                    Please don't Chat/PM me for help, unless mod related
                    SG-4860 24.11 | Lab VMs 2.8, 24.11

                    1 Reply Last reply Reply Quote 0
                    • stan-qazS
                      stan-qaz
                      last edited by

                      A fix for 2.1 was added to git, mentioned in the other topic.

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post
                      Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.