Compare commits

..

2 commits

Author SHA1 Message Date
Alexander Dietrich a04218ba87 Clean up name mangling function 2019-03-30 20:25:48 +01:00
Alexander Dietrich 2c989452c6 Parse tokudan's images.list instead of the manifest 2019-03-30 20:25:48 +01:00

View file

@ -1,58 +1,31 @@
<?php <?php
/* /*
Plugin Name: Freifunk Hamburg Firmware List Shortcode Plugin Name: Freifunk Hamburg Firmware Shortcodes
Plugin URI: http://mschuette.name/ Plugin URI: https://github.com/freifunkhamburg/freifunk-versions
Description: Defines shortcodes to display Freifunk Hamburg Firmware versions Description: Shortcodes for Freifunk Hamburg firmware information
Version: 0.5dev Author: Freifunk Hamburg
Author URI: https://github.com/freifunkhamburg
Author: Martin Schuette Author: Martin Schuette
Author URI: http://mschuette.name/ Author URI: https://mschuette.name/
Licence: 2-clause BSD Licence: 2-Clause BSD
*/ */
define( 'FF_HH_UPDATES_URL', 'https://updates.hamburg.freifunk.net/' ); define( 'FIRMWARE_BASE_URL', 'https://updates.hamburg.freifunk.net' );
define( 'FF_HH_CACHETIME', 1 ); define( 'FIRMWARE_CACHETIME', 1 );
/* gets metadata from URL, handles caching */ // Download firmware list and return the current release.
function ff_hh_getmanifest( $branch_url, $domain, $branch ) { function firmware_get_release( $base_url, $domain, $branch ) {
// Caching $cache_key = 'ff_firmware_release_' . $domain . '_' . $branch;
$cache_key = 'ff_hh_manifest_' . $domain . '_' . $branch; if ( false === ( $sw_ver = get_transient( $cache_key ) ) ) {
if ( WP_DEBUG || ( false === ( $manifest = get_transient( $cache_key ) ) ) ) { $sw_ver = '???';
$manifest = array(); $url = "$base_url/$domain/$branch/images/images.list";
$url = $branch_url . '/sysupgrade/' . $branch . '.manifest'; $http_response = wp_remote_get( $url );
$http_response = wp_remote_get( $url ); // TODO: error handling
$input = wp_remote_retrieve_body( $http_response ); $input = wp_remote_retrieve_body( $http_response );
foreach ( explode( "\n", $input ) as $line ) { foreach ( explode( "\n", $input ) as $line ) {
$ret = sscanf( $line, '%s %s %s %s', $hw, $sw_ver, $hash, $filename ); $ret = sscanf( $line, 'RELEASE=%s', $sw_ver );
if ( $ret === 4 ) { if ( $ret === 1 ) {
if ( preg_match( '/^(.*)-v(\d+)$/', $hw, $matches ) ) {
$hw = $matches[1];
$hw_ver = $matches[2];
} else {
$hw_ver = '1';
}
$manifest[$hw][$hw_ver] = $filename;
}
}
$cachetime = FF_HH_CACHETIME * MINUTE_IN_SECONDS;
set_transient( $cache_key, $manifest, $cachetime );
}
return $manifest;
}
/* gets latest version from first manifest line */
function ff_hh_getlatest( $branch_url, $domain, $branch ) {
// Caching
$cache_key = 'ff_hh_latestversion_' . $domain . '_' . $branch;
if ( false === ( $sw_ver = get_transient( $cache_key ) ) ) {
$sw_ver = 'unknown';
$url = $branch_url . '/sysupgrade/' . $branch . '.manifest';
$input = wp_remote_retrieve_body( wp_remote_get( $url ) );
foreach ( explode( "\n", $input ) as $line ) {
$ret = sscanf( $line, '%s %s %s %s', $hw, $sw_ver, $hash, $filename );
if ( $ret === 4 ) {
// break processing on first matching line // break processing on first matching line
$cachetime = FF_HH_CACHETIME * MINUTE_IN_SECONDS; $cachetime = FIRMWARE_CACHETIME * MINUTE_IN_SECONDS;
set_transient( $cache_key, $sw_ver, $cachetime ); set_transient( $cache_key, $sw_ver, $cachetime );
break; break;
} }
@ -61,14 +34,65 @@ function ff_hh_getlatest( $branch_url, $domain, $branch ) {
return $sw_ver; return $sw_ver;
} }
if ( ! shortcode_exists( 'ff_hh_latestversion' ) ) { // Download firmware list and return the firmware versions.
add_shortcode( 'ff_hh_latestversion', 'ff_hh_shortcode_latestversion' ); // The returned array is structured like this:
// versions[hardware_name][hardware_version][factory|upgrade] => URL
function firmware_get_versions( $base_url, $domain, $branch ) {
$release = firmware_get_release( $base_url, $domain, $branch );
$factory_regex = "/^(?:.*$release-)(.*)\.(?:bin|img|img\.gz)$/";
$upgrade_regex = "/^(?:.*$release-)(.*)(?:-sysupgrade\..*)$/";
$cache_key = 'ff_firmware_versions_' . $domain . '_' . $branch;
if ( WP_DEBUG || ( false === ( $versions = get_transient( $cache_key ) ) ) ) {
$versions = [];
$url = "$base_url/$domain/$branch/images/images.list";
$http_response = wp_remote_get( $url );
$input = wp_remote_retrieve_body( $http_response );
foreach ( explode( "\n", $input ) as $line ) {
$ret = sscanf( $line, '%s %s', $folder, $filename );
if ( $ret !== 2 ) {
continue;
}
$url = "$base_url/$domain/$branch/images/$folder/$filename";
if ( $folder === 'sysupgrade' ) {
$result = firmware_parse_version( $filename, $upgrade_regex );
if ( $result !== NULL ) {
$versions[$result[0]][$result[1]]['upgrade'] = $url;
}
} else {
$result = firmware_parse_version( $filename, $factory_regex );
if ( $result !== NULL ) {
$versions[$result[0]][$result[1]]['factory'] = $url;
}
}
}
$cachetime = FIRMWARE_CACHETIME * MINUTE_IN_SECONDS;
set_transient( $cache_key, $versions, $cachetime );
}
return $versions;
} }
function firmware_parse_version( $filename, $regex ) {
if ( preg_match( $regex, $filename, $matches ) ) {
$hw = $matches[1];
$hw_ver = '1';
if ( preg_match( '/^(.*?)-?v(\d+)$/', $hw, $matches ) ) {
$hw = $matches[1];
$hw_ver = $matches[2];
}
return [$hw, $hw_ver];
} else {
return NULL;
}
}
// Example: // Example:
// [ff_hh_latestversion] // [ff_firmware_release]
// [ff_hh_latestversion domain="ffhh-sued" branch="experimental"] // [ff_firmware_release domain="ffhh" branch="experimental"]
function ff_hh_shortcode_latestversion( $atts, $content, $name ) { function firmware_release( $atts, $content, $name ) {
$domain = 'ffhh'; $domain = 'multi';
$branch = 'stable'; $branch = 'stable';
if ( is_array( $atts ) ) { if ( is_array( $atts ) ) {
if ( array_key_exists( 'domain', $atts ) && ! empty( $atts['domain'] ) ) { if ( array_key_exists( 'domain', $atts ) && ! empty( $atts['domain'] ) ) {
@ -78,24 +102,18 @@ function ff_hh_shortcode_latestversion( $atts, $content, $name ) {
$branch = $atts['branch']; $branch = $atts['branch'];
} }
} }
$sw_ver = firmware_get_release( FIRMWARE_BASE_URL, $domain, $branch );
$branch_url = FF_HH_UPDATES_URL . $domain . '/' . $branch;
if ( $domain === 'multi' ) { $branch_url = $branch_url . '/images'; }
$sw_ver = ff_hh_getlatest( $branch_url, $domain, $branch );
$outstr = "<span class=\"ff $name\">$sw_ver</span>"; $outstr = "<span class=\"ff $name\">$sw_ver</span>";
return $outstr; return $outstr;
} }
if ( ! shortcode_exists( 'ff_hh_versions' ) ) {
add_shortcode( 'ff_hh_versions', 'ff_hh_shortcode_versions' );
}
// Example: // Example:
// [ff_hh_versions] // [ff_firmware_versions]
// [ff_hh_versions domain="ffhh-sued" branch="experimental" grep="ubiquiti"] // [ff_firmware_versions prefix="ubiquiti,ubnt" filter="ac-pro"]
function ff_hh_shortcode_versions( $atts, $content, $name ) { function firmware_versions( $atts, $content, $name ) {
$domain = 'ffhh'; $domain = 'multi';
$branch = 'stable'; $branch = 'stable';
$grep = false; $prefix = false;
$filter = false; $filter = false;
if ( is_array( $atts ) ) { if ( is_array( $atts ) ) {
if ( array_key_exists( 'domain', $atts ) && ! empty( $atts['domain'] ) ) { if ( array_key_exists( 'domain', $atts ) && ! empty( $atts['domain'] ) ) {
@ -104,163 +122,131 @@ function ff_hh_shortcode_versions( $atts, $content, $name ) {
if ( array_key_exists( 'branch', $atts ) && ! empty( $atts['branch'] ) ) { if ( array_key_exists( 'branch', $atts ) && ! empty( $atts['branch'] ) ) {
$branch = $atts['branch']; $branch = $atts['branch'];
} }
if ( array_key_exists( 'grep', $atts ) && ! empty( $atts['grep'] ) ) { if ( array_key_exists( 'prefix', $atts ) && ! empty( $atts['prefix'] ) ) {
$grep = $atts['grep']; $prefix = explode ( ',', $atts['prefix'] );
} }
if ( array_key_exists( 'filter', $atts ) && ! empty( $atts['filter'] ) ) { if ( array_key_exists( 'filter', $atts ) && ! empty( $atts['filter'] ) ) {
$filter = explode ( ',', $atts['filter'] ); $filter = explode ( ',', $atts['filter'] );
} }
} }
$branch_url = FF_HH_UPDATES_URL . $domain . '/' . $branch; $versions = firmware_get_versions( FIRMWARE_BASE_URL, $domain, $branch );
if ( $domain === 'multi' ) { $branch_url = $branch_url . '/images'; } if ( $prefix ) {
$manifest = ff_hh_getmanifest( $branch_url, $domain, $branch ); $filtered = [];
foreach ( $versions as $hw => $hw_versions ) {
$outstr = "<div class=\"ff $name\">"; foreach ( $prefix as $pfx ) {
$outstr .= '<table><tr><th>Modell</th><th>Erstinstallation</th><th>Aktualisierung</th></tr>'; if ( strpos ( $hw, $pfx ) === 0 ) {
$hw = substr( $hw, strlen($pfx) );
ksort($manifest); $hw = trim( $hw, '-' );
foreach ( $manifest as $hw => $versions ) { $filtered[$hw] = $hw_versions;
// select some models }
if ( $grep && ( false === strpos( $hw, $grep ) ) ) { }
continue; }
$versions = $filtered;
} }
// filter others
if ( $filter ) { if ( $filter ) {
$filtered = false; $filtered = [];
foreach ( $versions as $hw => $hw_versions ) {
foreach ( $filter as $flt ) { foreach ( $filter as $flt ) {
if ( strpos ( $hw, $flt ) !== false ) { if ( strpos ( $hw, $flt ) === FALSE ) {
$filtered = true; $filtered[$hw] = $hw_versions;
break;
} }
} }
if ( $filtered ) {
continue;
} }
$versions = $filtered;
} }
$hw = ff_hh_beautify_hw_name( $hw, $grep ); $outstr = "\n<div class=\"ff $name\">";
$outstr .= "\n<table>\n<tr><th>Modell</th><th>Erstinstallation</th><th>Aktualisierung</th></tr>";
ksort($versions);
foreach ( $versions as $hw => $hw_versions ) {
$hw = firmware_beautify_hw_name( $hw, $prefix );
$outstr .= sprintf( "\n<tr><td>%s</td>", $hw ); $outstr .= sprintf( "\n<tr><td>%s</td>", $hw );
// factory versions // factory images
$hw_ver_links = array(); $factory_links = [];
foreach ( $versions as $hw_ver => $filename ) { foreach ( $hw_versions as $hw_ver => $urls ) {
if ( strpos( $hw, 'Unifi Ac Pro' ) || strpos( $hw, 'Unifi Ac Lite' ) ) { if ( ! array_key_exists( 'factory', $urls ) ) {
continue; continue;
} }
$factory_url = $urls['factory'];
$filename = str_replace( '-sysupgrade', '', $filename ); $factory_links[] = "<a href=\"$factory_url\">$hw_ver.x</a>";
if (strpos($filename,'netgear') !== false) {
$filename = str_replace( '.bin', '.img', $filename );
$filename = str_replace( '.tar', '.img', $filename );
} }
$hw_ver_links[] = sprintf( if ( count($factory_links) > 0 ) {
'<a href="%s%s">%s.x</a>', $outstr .= '<td>Version ' . join( ', ', $factory_links ) . '</td>';
$branch_url . '/factory/',
$filename,
$hw_ver
);
}
if ( count($hw_ver_links) > 0) {
$outstr .= '<td>Hardware Ver. ' . join( ', ', $hw_ver_links ) . '</td>';
} else { } else {
$outstr .= '<td><i>Benutze das Image</br>zur Aktualisierung</i></td>'; $outstr .= '<td></td>';
} }
// sysupgrade versions // upgrade images
$hw_ver_links = array(); $upgrade_links = [];
foreach ( $versions as $hw_ver => $filename ) { foreach ( $hw_versions as $hw_ver => $urls ) {
$hw_ver_links[] = sprintf( if ( ! array_key_exists( 'upgrade', $urls ) ) {
'<a href="%s%s">%s.x</a>', continue;
$branch_url . '/sysupgrade/',
$filename,
$hw_ver
);
} }
$outstr .= '<td>Hardware Ver. ' . join( ', ', $hw_ver_links ) . '</td>'; $upgrade_url = $urls['upgrade'];
$upgrade_links[] = "<a href=\"$upgrade_url\">$hw_ver.x</a>";
$outstr .= '</tr>'; }
if ( count($upgrade_links) > 0 ) {
$outstr .= '<td>Version ' . join( ', ', $upgrade_links ) . '</td>';
} else {
$outstr .= '<td></td>';
} }
$outstr .= '</table>'; $outstr .= "</tr>";
$outstr .= '</div>'; }
// $outstr .= '<pre>'.print_r( $manifest, true ).'</pre>';
$outstr .= "\n</table>";
$outstr .= "\n</div>\n";
return $outstr; return $outstr;
} }
// some crude rules to add capitalization and whitespace to the // Add capitalization and whitespace to the hardware model name.
// hardware model name. function firmware_beautify_hw_name( $hw, $prefix ) {
// set $discard_vendor to strip the vendor name $vendor = '';
// (used for single-vendor lists, e.g. $discard_vendor = 'tp-link' ) if ( $prefix ) {
function ff_hh_beautify_hw_name( $hw, $discard_vendor = '' ) { $vendor = $prefix[0];
if ( ! strncmp( $hw, 'tp-link', 7 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( '-', ' ', $hw );
$hw = str_replace( ' TL ', ' TL-', $hw );
} elseif ( ! strncmp( $hw, 'ubiquiti', 8 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = str_replace( 'bullet-m', 'bullet-m', $hw );
$hw = str_replace( '-', ' ', $hw );
$hw = ucwords( $hw );
} elseif ( ! strncmp( $hw, 'ubnt', 4 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = str_replace( 'erx', 'ER-X', $hw );
$hw = str_replace( 'sfp', 'SFP', $hw );
$hw = trim( $hw, ' -' );
$hw = ucwords( $hw );
} elseif ( ! strncmp( $hw, 'd-link', 6 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( '-', ' ', $hw );
$hw = str_replace( ' DIR ', ' DIR-', $hw );
} elseif ( ! strncmp( $hw, 'linksys', 7 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( '-', ' ', $hw );
$hw = str_replace( ' WRT', ' WRT-', $hw );
} elseif ( ! strncmp( $hw, 'buffalo', 7 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( 'HP-AG300H-WZR-600DHP', 'HP-AG300H & WZR-600DHP', $hw );
$hw = str_replace( '-WZR', 'WZR', $hw );
} elseif ( ! strncmp( $hw, 'netgear', 7 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( '-', '', $hw );
} elseif ( ! strncmp( $hw, 'allnet', 6 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( '-', '', $hw );
} elseif ( ! strncmp( $hw, 'gl-', 3 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( '-', '', $hw );
} elseif ( ! strncmp( $hw, 'onion-omega', 11 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
} elseif ( ! strncmp( $hw, 'alfa', 4 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( '-', '', $hw );
} elseif ( ! strncmp( $hw, 'wd', 2 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( '-', '', $hw );
} elseif ( ! strncmp( $hw, '8devices', 8 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( 'CARAMBOLA2-BOARD', 'Carambola 2', $hw );
$hw = str_replace( '-', '', $hw );
} elseif ( ! strncmp( $hw, 'meraki', 6 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( 'meraki', '', $hw );
$hw = str_replace( '-', '', $hw );
} elseif ( ! strncmp( $hw, 'openmesh', 8 ) ) {
if ( $discard_vendor ) $hw = str_replace( $discard_vendor, '', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( 'openmesh', '', $hw );
$hw = str_replace( '-', '', $hw );
} }
if ( $vendor === '8devices' ) {
$hw = str_replace( 'carambola2-board', 'carambola 2', $hw );
$hw = ucwords( $hw );
} elseif ( $vendor === 'buffalo' ) {
$hw = str_replace( 'hp-ag300h-wzr-600dhp', 'hp-ag300h & wzr-600dhp', $hw );
$hw = strtoupper( $hw );
} elseif ( $vendor === 'd-link' ) {
$hw = str_replace( '-', ' ', $hw );
$hw = str_replace( 'dir ', 'dir-', $hw );
$hw = strtoupper( $hw );
} elseif ( $vendor === 'onion' ) {
$hw = ucwords( $hw );
} elseif ( $vendor === 'tp-link' ) {
$hw = str_replace( 'n-nd', 'n/nd', $hw );
$hw = str_replace( '-', ' ', $hw );
$hw = str_replace( 'tl ', 'tl-', $hw );
$hw = strtoupper( $hw );
$hw = str_replace( 'ARCHER', 'Archer', $hw );
} elseif ( $vendor === 'ubiquiti' ) {
$hw = str_replace( '-', ' ', $hw );
$hw = ucwords( $hw );
$hw = str_replace( 'Ac', 'AC', $hw );
$hw = str_replace( 'Ap', 'AP', $hw );
$hw = str_replace( 'Erx', 'ER-X', $hw );
$hw = str_replace( 'Sfp', 'SFP', $hw );
$hw = str_replace( 'Xw', 'XW', $hw );
} else {
$hw = strtoupper( $hw );
}
return $hw; return $hw;
} }
if ( ! shortcode_exists( 'ff_firmware_release' ) ) {
add_shortcode( 'ff_firmware_release', 'firmware_release' );
}
if ( ! shortcode_exists( 'ff_firmware_versions' ) ) {
add_shortcode( 'ff_firmware_versions', 'firmware_versions' );
}