sig_handler(): Split a long line in two
[privoxy.git] / utils / create-package-feed.pl
old mode 100644 (file)
new mode 100755 (executable)
index 07a7e17..68781ad
 #!/usr/local/bin/perl
-#< LICENSE: WTFPL >
+
+############################################################################
+# create-package-feed.pl
+#
+# Generates an RSS feed for the released files.
+#
+# Usage:
+# create-package-feed.pl "path/to/release/files" "path/to/rss/outputfile"
+#
+# Copyright (c) 2016 "Unknown", Fabian Keil <fk@fabiankeil.de>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+############################################################################
+
 use warnings;
 use strict;
-use Digest::SHA1;
+use Digest::SHA;
 my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
 my @days   = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
 
-#< Config START >
-my $scan_dir   = '/xxxxxxxxxxxxxxxxxxxxxx/sf-download/';
 my $base_dlurl = 'https://www.privoxy.org/sf-download-mirror/';
-my $save_rss_file ='/xxxxxxxxxxxxxxxxxxxxxx/release.xml'; # e.g., release.rss
-my $maxlimit = 1000;
-
-#< Config END >
-
-my @Array = ();
-my $i     = 0;
-my $sec;
-my $min;
-my $hour;
-my $mday;
-my $mon;
-my $year;
-my $wday;
-my $yday;
-my $isdst;
-my $target;
-my $target_sha1;
-my $target_uri;
-my $target_time;
-my $target_line;
+my $max_advertised_files = 100;
 
-#
-# 1st & 2nd directory should NOT contain ANY 'FILES'. (expecting only 'Directory')
-#
-opendir(D1, $scan_dir) or die "Can't open 1st directory! /";
-while (my $fi1 = readdir(D1)) {
-    next if ($fi1 =~ m/^\./);
-
-    opendir(D2, $scan_dir . $fi1 . '/')
-        or die "Can't open 2nd directory! /$fi1";
-    while (my $fi2 = readdir(D2)) {
-        next if ($fi2 =~ m/^\./);
-
-## start listing /OS/Version/FILE
-        opendir(D3, $scan_dir . $fi1 . '/' . $fi2 . '/')
-            or die "Can't open 3rd directory! /$fi1/$fi2";
-        while (my $fi3 = readdir(D3)) {
-            next if ($fi3 =~ m/^\./);
-            $target = $scan_dir . $fi1 . '/' . $fi2 . '/' . $fi3;
-            next if (!-e $target);    # skip if file is not exist
-
-            # Get SHA-1 hash
-            my $filedata;
-            unless (open $filedata, $target) { next; }
-            my $sha1 = Digest::SHA1->new;
-            $sha1->addfile($filedata);
-            close $filedata;
-            $target_sha1 = $sha1->hexdigest;
-
-            # URI and Time
-            $target_uri  = $fi1 . '/' . $fi2 . '/' . $fi3;
-            $target_time = (stat $target)[9];
-
-            # RSS line
-            $target_line =
-                '<item><title><![CDATA[' . $target_uri . ']]></title>';
-            $target_line .=
-                  '<description><![CDATA['
-                . $target_uri
-                . ' (SHA-1: '
-                . $target_sha1
-                . ')]]></description>';
-            $target_line .=
-                  '<link>'
-                . $base_dlurl
-                . $target_uri
-                . '</link><guid>'
-                . $base_dlurl
-                . $target_uri
-                . '</guid>';
-            $target_line .= '<pubDate>';
-            ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
-                gmtime($target_time);
-            $target_line .=
-                  "$days[$wday], $mday $months[$mon] "
-                . ($year + 1900)
-                . " $hour:$min:$sec GMT";
-            $target_line .= '</pubDate></item>';
-
-            # Add it to Array
-            $Array[$i] = ([$target_time, $target_line]);
-            $i++;
-            die "maxlimit $maxlimit reached!" unless ($i < $maxlimit);
+sub generate_rss_item($$$$) {
+    my ($target, $target_uri, $target_time, $target_sha256) = @_;
+
+    my $rss_item;
+    my $escaped_target_uri = $target_uri;
+    $escaped_target_uri =~ s@ @%20@g;
+
+    # RSS line
+    $rss_item =
+        '<item><title><![CDATA[' . $target_uri . ']]></title>';
+    $rss_item .=
+        '<description><![CDATA['
+        . $target_uri
+        . ' (SHA-256: '
+        . $target_sha256
+        . ')]]></description>';
+    $rss_item .=
+        '<link>'
+        . $base_dlurl
+        . $escaped_target_uri
+        . '</link><guid>'
+        . $base_dlurl
+        . $escaped_target_uri
+        . '</guid>';
+    $rss_item .= '<pubDate>';
+    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
+        gmtime($target_time);
+    $rss_item .= sprintf("%s, %s %s %d %.2d:%.2d:%.2d GMT",
+                         $days[$wday], $mday, $months[$mon], ($year + 1900),
+                         $hour, $min, $sec);
+    $rss_item .= '</pubDate></item>';
+    $rss_item .= "\n";
+
+    return $rss_item;
+}
+
+sub get_sha256_sum($) {
+    my $file = shift;
+
+    open(my $fd, "<", $file)
+        or die "Can't open '$file' to generate checksum $!";
+    my $sha256 = Digest::SHA->new("SHA-256");
+    $sha256->addfile($fd);
+    close($fd);
+
+    return $sha256->hexdigest;
+}
+
+sub get_released_files($) {
+    my $scan_dir = shift;
+
+    my @Array = ();
+    my $i     = 0;
+    my $target;
+    my $target_sha256;
+    my $target_uri;
+    my $target_time;
+    my $target_line;
+
+    opendir(my $D1, $scan_dir) or die "Can't open 1st directory! /";
+    while (my $fi1 = readdir($D1)) {
+        next if ($fi1 =~ m/^\./);
+        next if ($fi1 eq 'OldFiles' or $fi1 eq 'pkgsrc');
+
+        opendir(my $D2, $scan_dir . $fi1 . '/')
+            or die "Can't open 2nd directory! /$fi1";
+        while (my $fi2 = readdir($D2)) {
+            next if ($fi2 =~ m/^\./);
+
+            # Start listing /OS/Version/FILE
+            opendir(my $D3, $scan_dir . $fi1 . '/' . $fi2 . '/')
+                or die "Can't open 3rd directory! /$fi1/$fi2";
+            while (my $fi3 = readdir($D3)) {
+                next if ($fi3 =~ m/^\./);
+                $target = $scan_dir . $fi1 . '/' . $fi2 . '/' . $fi3;
+                next if (!-e $target);    # skip if file is not exist
+
+                $target_uri  = $fi1 . '/' . $fi2 . '/' . $fi3;
+                $target_time = (stat $target)[9];
+
+                $Array[$i] = ([$target_time, $target, $target_uri]);
+
+                $i++;
+            }
+            closedir($D3);
         }
-        closedir D3;
-## end listing /OS/Version/FILE
+        closedir($D2);
+    }
+    closedir($D1);
+
+    return sort { @$a[0] <=> @$b[0] } @Array;
+}
+
+sub generate_feed($) {
+    my $scan_dir = shift;
 
+    # Result = Full XML Codes
+    my $result = '<?xml version="1.0" encoding="utf-8"?>
+ <rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
+  <channel>
+   <title>Privoxy Releases</title>
+   <link>https://www.privoxy.org/announce.txt</link>
+   <description><![CDATA[Privoxy Releases RSS feed]]></description>
+   <pubDate>';
+    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = gmtime();
+    $result .=
+        "$days[$wday], $mday $months[$mon] "
+        . ($year + 1900)
+        . " $hour:$min:$sec GMT";
+    $result .= '</pubDate>';
+    $result .= "\n";
+
+    my @resArray = get_released_files($scan_dir);
+    my $i = @resArray - 1;
+    while ($max_advertised_files-- > 0 && $i >= 0) {
+        my $target_time =  $resArray[$i][0];
+        my $target = $resArray[$i][1];
+        my $target_uri =  $resArray[$i][2];
+
+        my $target_sha256 = get_sha256_sum($target);
+
+        my $rss_item = generate_rss_item($target, $target_uri, $target_time, $target_sha256);
+
+        $result .= $rss_item;
+        $i--;
     }
-    closedir D2;
+    $result .= '  </channel>
+   </rss>';
 
+    return $result;
 }
-closedir D1;
-
-# Result = Full XML Codes
-my $result =
-    '<?xml version="1.0" encoding="utf-8"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Privoxy Releases</title><link>https://www.privoxy.org/announce.txt</link><description><![CDATA[Privoxy Releases RSS feed]]></description><pubDate>';
-($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = gmtime();
-$result .=
-      "$days[$wday], $mday $months[$mon] "
-    . ($year + 1900)
-    . " $hour:$min:$sec GMT";
-$result .= '</pubDate>';
-
-# Sort Array
-my @resArray = sort { @$a[0] <=> @$b[0] } @Array;
-$i--;
-while ($i >= 0) { $result .= $resArray[$i][1]; $i--; }
-$result .= '</channel></rss>';
-
-# Save it.
-open(XMLF, "> $save_rss_file") or die "Failed to write XML file";
-print XMLF $result;
-close(XMLF);
+
+sub main() {
+    my $scan_dir = shift(@ARGV)
+        or die "Local package directory not specified (first argument)\n";
+    my $save_rss_file = shift(@ARGV)
+        or die "RSS output file path not specified (second argument)\n";
+
+    my $result = generate_feed($scan_dir);
+
+    open(my $XMLF, ">", $save_rss_file) or die "Failed to write XML file";
+    print $XMLF $result;
+    close($XMLF);
+}
+
+main();