psk_download.pl: don't verify cert hostname
[toast/webscraper/psk.git] / psk_download.pl
1 #!/usr/bin/perl
2
3 # mech-dump --all https://ebanking.bawagpsk.com/InternetBanking/InternetBanking?d=login&svc=BAWAG&ui=html&lang=de
4
5 use strict;
6 use warnings;
7 use Carp;
8 use 5.010;
9
10 use Config::Auto;
11 use WWW::Mechanize;
12
13 use Pod::Usage;
14 use Getopt::Long;
15 use File::Spec::Functions qw(catfile);
16 use File::Basename qw(dirname);
17 use IO::Socket::SSL;
18
19 use constant DEBUG => 0;
20
21 # options
22 debug("Parse options ...");
23 my $opt_help = 0;
24 my $opt_man  = 0;
25 GetOptions( 'help|?' => \$opt_help, 'man' => \$opt_man ) or pod2usage(2);
26 pod2usage( -verbose => 1 ) if ($opt_help);
27 pod2usage( -verbose => 2 ) if ($opt_man);
28
29 # get config
30 # $ENV{HOME} . '/.psk_downloadrc': verfuegernummer, pin
31 debug("Read config ...");
32 my $config = Config::Auto::parse();
33 croak "We need verfuegernummer and pin in $ENV{HOME}/.psk_downloadrc"
34     unless ( $config->{verfuegernummer}
35     && $config->{pin} );
36
37 my $dir = $ARGV[0] || $config->{dir} || dirname($0);
38 $dir =~ s{^~/}{$ENV{HOME}/};
39 croak "Directory '$dir' doesn't exist." unless -d $dir;
40
41 # login
42 debug("Log in ...");
43 my $url
44     = 'https://ebanking.bawagpsk.com/InternetBanking/InternetBanking?d=login&svc=BAWAG&ui=html&lang=de';
45 my $mech = WWW::Mechanize->new(
46     autocheck => 1,
47     ssl_opts  => {
48         SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
49         verify_hostname =>
50             0,    # this key is likely going to be removed in future LWP >6.04
51     }
52 );
53 $mech->add_header( 'Accept-Encoding' => 'identity' );    # no gzip
54 $mech->get($url);
55
56 my $r = $mech->submit_form(
57     form_name => 'loginForm',
58     fields    => {
59         dn  => $config->{verfuegernummer},
60         pin => $config->{pin},
61     },
62 );
63 croak "Couldn't submit form 'loginForm'." unless $r->is_success;
64
65 # after logging in we use the navigationform to go the the accountstatementlist
66 # built after the javascript function navigateTo
67 debug("Account statement list ...");
68 $r = $mech->submit_form(
69     form_name => 'navigationform',
70     fields    => { d => 'accountstatementlist', },
71 );
72 croak "Couldn't submit form 'navigationform'." unless $r->is_success;
73
74 # links to PDFs
75 debug("PDF links ...");
76 my @pdflinks = $mech->find_all_links( text => 'anfordern' );
77 croak "Couldn't find any download links." unless scalar @pdflinks;
78
79 debug("Loop over links ...");
80 for my $link (@pdflinks) {
81
82     # built after the javascript function getPdfStatement
83     my $onclick = $link->attrs->{'onclick'};
84
85     # 'onclick' => 'getPdfStatement(\'30\',\'07.10.2013\');',
86     my ( $index, $cd ) = ( $onclick =~ m/.*'(\d+)','([\d.]+)'.*/ );
87     debug( "Check $index of " . scalar @pdflinks . " ..." );
88
89     # download only once
90     my @files = glob "*_${cd}.pdf";
91     next if scalar @files > 0;
92
93     debug("Click download link ...");
94     $r = $mech->submit_form(
95         form_name => 'pdfstatementForm',
96         fields    => {
97             cd      => $cd,
98             asindex => $index,
99         },
100     ) or return;
101     croak "Couldn't submit form 'pdfstatementForm'." unless $r->is_success;
102
103     debug("Check contents for PDF ...");
104     my $content_type = $mech->content_type;
105     croak "No PDF." unless $content_type eq 'application/pdf';
106
107     debug("Save PDF ...");
108     my $filename = $mech->res->filename;
109     $filename =~ s/\.pdf$/_$cd.pdf/;
110     $filename = catfile( $dir, $filename );
111     $mech->save_content( $filename, binary => 1 ) unless -e $filename;
112
113     # set $mech back to accountstatementlist
114     $mech->back;
115 }
116
117 exit 0;
118
119 sub debug {
120     say "D: ", @_ if DEBUG;
121 }
122
123 __END__
124
125 =head1 NAME
126
127 psk_download.pl - Download account statements from PSK online banking
128
129 =head1 SYNOPSIS
130
131 psk_download.pl [directory]
132
133 =head1 DESCRIPTION
134
135 B<psk_download.pl> logs into the PSK online banking website and downloads
136 the account statement PDFs.
137
138 =head1 PARAMETERS
139
140 =over
141
142 =item B<directory> (optional)
143
144 Overrides the I<dir> parameter in the config file.
145 One of them is required.
146
147 =back
148
149 =head1 OPTIONS
150
151 =over
152
153 =item B<--help|?>
154
155 Short help.
156
157 =item B<--man>
158
159 Complete man page.
160
161 =back
162
163 =head1 FILES
164
165 =over
166
167 =item F<~/.psk_downloadrc> (required)
168
169 Required parameters: I<verfuegernummer>, I<pin>.
170
171 Optional parameter: I<dir> (target directory for downloads).
172 Overriden if a directory is passed to the script.
173 If both are missing, the script's directory is used.
174
175 Format: Anything that L<Config::Auto> understands, e.g. key=value.
176
177 Filename: Anything that L<Config::Auto> finds.
178
179 =back
180
181 =head1 COPYRIGHT AND LICENSE
182
183 Copyright 2016, gregor herrmann E<lt>gregor@toastfreeware.priv.atE<gt>
184
185 Copyright 2016, Philipp Spitzer E<lt>philipp@toastfreeware.priv.atE<gt>
186
187 This is free software; you can redistribute it and/or modify it under the
188 same terms as the Perl 5 programming language system itself.