My attempt to add a Dynimac DNS status widget
-
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
-
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 -
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.
-
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.
-
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.
-
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.
-
I think I got it into the git repository: https://github.com/bsdperimeter/pfsense/pull/413
That wasn't too painful!
-
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 -
A fix for 2.1 was added to git, mentioned in the other topic.