This patch originated from the thread that begins here: http://lists.infradead.org/pipermail/get_iplayer/2011-March/001078.html
While hacking on get_iplayer to download embedded media clips from a couple of other BBC web sites, I discovered a problem (explained in the commit message below) with the logic used to compute expiry dates for downloaded programmes. A few media clips had expiry dates too large for get_iplayer to handle, so it would bomb. This is an esoteric issue that will likely never affect normal iPlayer programmes, which of course expire fairly quickly. Still, I couldn't let a bug remain unfixed if I could help it. I also hope to work in general support for downloading from embedded clip URLs, and this patch would be necessary for that. Updated get_iplayer script here: https://github.com/dinkypumpkin/get_iplayer/raw/patched/get_iplayer Commit history here: https://github.com/dinkypumpkin/get_iplayer/commits/patched/ Patch follows - get_iplayer uses timegm() to calculate expiry dates for downloaded programmes. In 32-bit versions of perl or any perl < 5.10.1, timegm() croaks for any date greater than 2038-01-16 23:59:59. The current approach of setting year = 2038 for any dates in 2038 and after is insufficient to ensure a safe 32-bit date. This patch changes the code to run timegm() within an eval block. If timegm() croaks, epoch date is set to arbitrary safe value (2038-01-01 00:00:00). Redundant calls to to timegm() have also been removed. The problem corrected by this patch is very much an edge case, so far only observed when using a hacked get_iplayer to download media clips embedded in other BBC web sites. However, the logic is still incorrect, so this patch has been created to fix it. --- get_iplayer | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/get_iplayer b/get_iplayer index 81d6dea..3d68865 100755 --- a/get_iplayer +++ b/get_iplayer @@ -4839,15 +4839,15 @@ sub get_time_string { main::logger "DEBUG: $_ = $year, $mon, $mday, $hour, $min, $sec, $tzhour, $tzmin\n" if $opt->{debug}; # Sanity check date data return '' if $year < 1970 || $mon < 1 || $mon > 12 || $mday < 1 || $mday > 31 || $hour < 0 || $hour > 24 || $min < 0 || $min > 59 || $sec < 0 || $sec > 59 || $tzhour < -13 || $tzhour > 13 || $tzmin < -59 || $tzmin > 59; - # Year cannot be > 2032 so limit accordingly :-/ - $year = 2038 if $year > 2038; # Calculate the seconds difference between epoch_now and epoch_datestring and convert back into array_time - my $epoch = timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60; + my $epoch = eval { timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60; }; + # ensure safe 32-bit date if timegm croaks + if ( $@ ) { $epoch = timegm(0, 0, 0, 1, 0, 138, undef, undef, 0) - $tzhour*60*60 - $tzmin*60; }; my $rtn; if ( $diff ) { # Return time ago if ( $epoch < $diff ) { - my @time = gmtime( $diff - ( timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60 ) ); + my @time = gmtime( $diff - $epoch ); # The time() func gives secs since 1970, gmtime is since 1900 my $years = $time[5] - 70; $rtn = "$years years " if $years; @@ -4855,7 +4855,7 @@ sub get_time_string { return $rtn; # Return time to go } elsif ( $epoch > $diff ) { - my @time = gmtime( ( timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60 ) - $diff ); + my @time = gmtime( $epoch - $diff ); my $years = $time[5] - 70; $rtn = 'in '; $rtn .= "$years years " if $years; @@ -4868,7 +4868,7 @@ sub get_time_string { # Return time in epoch } else { # Calculate the seconds difference between epoch_now and epoch_datestring and convert back into array_time - return timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60; + return $epoch; } } -- 1.7.4.3 _______________________________________________ get_iplayer mailing list [email protected] http://lists.infradead.org/mailman/listinfo/get_iplayer

