--- /dev/null
+#!/usr/bin/perl
+
+# mech-dump --all https://ebanking.bawagpsk.com/InternetBanking/InternetBanking?d=login&svc=BAWAG&ui=html&lang=de
+
+use strict;
+use warnings;
+use Carp;
+use 5.010;
+
+use Config::Auto;
+use WWW::Mechanize;
+
+use Pod::Usage;
+use Getopt::Long;
+use File::Spec::Functions qw(catfile);
+use File::Basename qw(dirname);
+
+use constant DEBUG => 0;
+
+# options
+debug("Parse options ...");
+my $opt_help = 0;
+my $opt_man = 0;
+GetOptions( 'help|?' => \$opt_help, 'man' => \$opt_man ) or pod2usage(2);
+pod2usage( -verbose => 1 ) if ($opt_help);
+pod2usage( -verbose => 2 ) if ($opt_man);
+
+# get config
+# $ENV{HOME} . '/.psk_downloadrc': verfuegernummer, pin
+debug("Read config ...");
+my $config = Config::Auto::parse();
+croak "We need verfuegernummer and pin in $ENV{HOME}/.psk_downloadrc"
+ unless ( $config->{verfuegernummer}
+ && $config->{pin} );
+
+my $dir = $ARGV[0] || $config->{dir} || dirname($0);
+$dir =~ s{^~/}{$ENV{HOME}/};
+croak "Directory '$dir' doesn't exist." unless -d $dir;
+
+# login
+debug("Log in ...");
+my $url
+ = 'https://ebanking.bawagpsk.com/InternetBanking/InternetBanking?d=login&svc=BAWAG&ui=html&lang=de';
+my $mech = WWW::Mechanize->new( autocheck => 1, );
+$mech->add_header( 'Accept-Encoding' => 'identity' ); # no gzip
+$mech->get($url);
+
+my $r = $mech->submit_form(
+ form_name => 'loginForm',
+ fields => {
+ dn => $config->{verfuegernummer},
+ pin => $config->{pin},
+ },
+);
+croak "Couldn't submit form 'loginForm'." unless $r->is_success;
+
+# after logging in we use the navigationform to go the the accountstatementlist
+# built after the javascript function navigateTo
+debug("Account statement list ...");
+$r = $mech->submit_form(
+ form_name => 'navigationform',
+ fields => { d => 'accountstatementlist', },
+);
+croak "Couldn't submit form 'navigationform'." unless $r->is_success;
+
+# links to PDFs
+debug("PDF links ...");
+my @pdflinks = $mech->find_all_links( text => 'anfordern' );
+croak "Couldn't find any download links." unless scalar @pdflinks;
+
+debug("Loop over links ...");
+for my $link (@pdflinks) {
+
+ # built after the javascript function getPdfStatement
+ my $onclick = $link->attrs->{'onclick'};
+
+ # 'onclick' => 'getPdfStatement(\'30\',\'07.10.2013\');',
+ my ( $index, $cd ) = ( $onclick =~ m/.*'(\d+)','([\d.]+)'.*/ );
+ debug( "Check $index of " . scalar @pdflinks . " ..." );
+
+ # download only once
+ my @files = glob "*_${cd}.pdf";
+ next if scalar @files > 0;
+
+ debug("Click download link ...");
+ $r = $mech->submit_form(
+ form_name => 'pdfstatementForm',
+ fields => {
+ cd => $cd,
+ asindex => $index,
+ },
+ ) or return;
+ croak "Couldn't submit form 'pdfstatementForm'." unless $r->is_success;
+
+ debug("Check contents for PDF ...");
+ my $content_type = $mech->content_type;
+ croak "No PDF." unless $content_type eq 'application/pdf';
+
+ debug("Save PDF ...");
+ my $filename = $mech->res->filename;
+ $filename =~ s/\.pdf$/_$cd.pdf/;
+ $filename = catfile( $dir, $filename );
+ $mech->save_content( $filename, binary => 1 ) unless -e $filename;
+
+ # set $mech back to accountstatementlist
+ $mech->back;
+}
+
+exit 0;
+
+sub debug {
+ say "D: ", @_ if DEBUG;
+}
+
+__END__
+
+=head1 NAME
+
+psk_download.pl - Download account statements from PSK online banking
+
+=head1 SYNOPSIS
+
+psk_download.pl [directory]
+
+=head1 DESCRIPTION
+
+B<psk_download.pl> logs into the PSK online banking website and downloads
+the account statement PDFs.
+
+=head1 PARAMETERS
+
+=over
+
+=item B<directory> (optional)
+
+Overrides the I<dir> parameter in the config file.
+One of them is required.
+
+=back
+
+=head1 OPTIONS
+
+=over
+
+=item B<--help|?>
+
+Short help.
+
+=item B<--man>
+
+Complete man page.
+
+=back
+
+=head1 FILES
+
+=over
+
+=item F<~/.psk_downloadrc> (required)
+
+Required parameters: I<verfuegernummer>, I<pin>.
+
+Optional parameter: I<dir> (target directory for downloads).
+Overriden if a directory is passed to the script.
+If both are missing, the script's directory is used.
+
+Format: Anything that L<Config::Auto> understands, e.g. key=value.
+
+Filename: Anything that L<Config::Auto> finds.
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2016, gregor herrmann E<lt>gregor@toastfreeware.priv.atE<gt>
+
+Copyright 2016, Philipp Spitzer E<lt>philipp@toastfreeware.priv.atE<gt>
+
+This is free software; you can redistribute it and/or modify it under the
+same terms as the Perl 5 programming language system itself.