#!/usr/bin/perl -w
# author:    Jan Peter Hecking <jhecking@informatik.uni-rostock.de>
# version:   1.0
# last edit: 1999 Apr 29, 21:57:48
#
# This script fetches the list of updated/new packages from SuSE's website at
# http://www.suse.de/patches/60_update.html or any other website that's
# specified on the command line. It looks for all packages that are listed with
# a date within the last 7 days and prints those out. It was written to be used
# as a cron-tab entry.

use strict;
use vars qw(
    @packagelist %update %new
    $new $nr $part
    $linknr $name $size $date $desc $link
    $today $since
    $last
    $days $url $show $help $quiet $debug
);

use Getopt::Long qw( GetOptions );
use POSIX qw( strftime );

$days = 7;                      # check for new packages in the last 7 days
$url  = "http://www.suse.de/patches/60_update.html"; # url to fetch with lynx
$show = "name date desc link";  # show these parts of the fetched information

Getopt::Long::Configure("pass_through");
GetOptions( "days|d=i"  => \$days,
            "url|u=s"   => \$url,
            "show|s=s"  => \$show,
            "help|?"    => \$help,
            "quiet|q"   => \$quiet,
            "debug"     => \$debug,
);

if ($help or @ARGV) { 
    &usage(@ARGV); 
};

$today = strftime "%d.%m.%y", localtime(time);
$since = strftime "%d.%m.%y", localtime(time-($days*24*60*60));

@packagelist = `lynx -dump $url`;

for (@packagelist) {

    if ( ($linknr,$name,$size,$date,$desc) = 
            m{^
                \s+
                \[(\d+)\]               # link nr. => $linknr
                ([^(]+)                 # packet name => $name
                \s+
                (?:\((\d+)\ Kb\)\s+)?   # optional size => $size
                (\d+\.\d+\.\d+)         # date => $date
                \s+
                (.*)                    # packet description => $desc
            $}xi ) {
        print join("#", $linknr, $name, $size, $date, $desc), "\n" if $debug;
        $desc =~ s/\[\d+\]//;
        $size = "unknown" if not $size;
        $update{$linknr} = {
            name    =>  $name,
            size    =>  $size,
            date    =>  $date,
            desc    =>  $desc,
        };
        $last = $linknr;
        ($linknr,$name,$size,$date,$desc) = "";
    } elsif (($linknr, $link) = /^\s+(\d+)\.\s+(.*)\s*$/) {
        if (exists $update{$linknr}) {
            $update{$linknr}{link} = $link;
        }
    } elsif ($last) {
        ($desc) = /^\s+(.*)\s*$/;
        if ($desc =~ /[-_]{3}/ or $desc =~ /^$/) {
            $last = "";
        } else {
            $desc =~ s/\[\d+\]//;
            $update{$last}{desc} .= " $desc";
        }
    } else {
        $last = "";
    }
}
    
for (keys %update) {
    if (&in_time_range($update{$_}{date}, $since, $today)) {
        $new{$_} = $update{$_};
    }
}

$new = keys %new;
    
printf("%d updated/new package%s between %s and %s\nat %s:\n\n",
        $new, ($new==1 ? "" : "s"), $since, $today, $url)
        unless $quiet and not $new;
for $nr (keys %new) {
    for $part (split /\s+/, $show) {
        print "$part: $update{$nr}{$part}\n"
            if (exists $update{$nr}{$part});
    }
    print "\n";
}
print "no updated/new packages found\n" unless $new or $quiet;

if ($debug) {
    my @keys  = keys %update;
    my %dates = map {$update{$_}{date},""} @keys;
    print "there were updated/new packages on the following dates:\n",
        join(", ", sort keys %dates), "\n";
}

exit $new;

sub in_time_range {
    my ($day, $first, $last) = @_;
    for ($day, $first, $last) {
        $_ = join("", reverse split(/\./, $_));
    }
    return $day >= $first and $day <= $last;
}

sub usage {
    for (@_) {
        print "Unknown option: $_\n";
    }
    $0 =~ m|[^/]*$|;
    my $cmd = $&;
    print <<__EOT__;

Usage: $cmd [OPTIONS]
Fetch the list of updates, bugfixes and patches from SuSE's website and
list those that have occured within the last 7 days.

  -d, --days int       list entries for the last int days (default: 7)
  -u, --url  url       fetch this url instead of 
                       http://www.suse.de/patches/60_update.html
  -s, --show list      space seperated list of information to show for each
                       package: a subset of "date desc link name size"
                       (default: "name date desc link")
  -q, --quiet          don't print anything if no updated/new packages were
                       found

The exit status is the number of updated/new packages.
__EOT__

    exit 0;
}
