Add Goteo data collect scripts.
[gnupg-doc.git] / misc / accounts.gnupg.net / htbin / goteo-collect.cgi
1 #!/usr/bin/perl -T
2
3 # goteo-collect.cgi   - Collect data for rewards of the 2013 Goteo campaign
4 # Copyright (C) 2014 g10 Code GmbH
5 #
6 # This file is free software; as a special exception the author gives
7 # unlimited permission to copy and/or distribute it, with or without
8 # modifications, as long as this notice is preserved.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
12 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14 # This scripts presents a customized page to collect information for
15 # the Goteo campaign rewards.  it expects a template file
16 # goteo-collect.html.in with certain '@' delimited variables and data
17 # file /var/log/gnupg.net/goteo-collect.input with the information to
18 # be presented to the user.  The result will be logged to the file
19 # /var/log/gnupg.net/goteo-collect in a mail header like format to be
20 # later processed using GNU recutils or addrutil.  The input is
21 # expected to be colon separated with one record per line.  All values
22 # use percent encoding but may use unencoded spaces.  The fields are:
23 #
24 # 1. id      := A random string to identify the record.  This is
25 #               part of the URL send by mail to the respective
26 #               contributor.
27 # 2. account := The Goteo account name
28 # 3. name    := Name of the contributor
29 # 4. reward  := Type of the reward: 't' = t-shirt
30 #                                   'm' = mail address
31 #                                   's' = sticker
32 # 5. mail    := real mail address
33 # 6. address := The address data (only required for 't')
34
35 #
36 # Note that this script needs libmime-base32-perl.
37
38 # Preparing the inpout data.  We received the Input data as
39 # spreadshit. The follwoing steps have been used to create the input
40 # data:
41 #  - Use gnumeric to create a CSV file.
42 #  - Run addrutil like this
43 #
44 #     tail -n+2 FILE \
45 #       ./addrutil -FGoteo-ID -FUser -FName -FMail -FAmount -FProblem \
46 #                  -FAnon -FReward -FAddress -FDate --readcsv   \
47 #       | sed '/^Address:/ s/ , , ,//' | sed '/^Address:/ s/,/\n/g' > data
48 #
49 #    Now we have the data in an easy to read format.  The tool addrutil is
50 #    available at 'http://git.gnupg.org/cgi-bin/gitweb.cgi\
51 #                  ?p=wk-misc.git;f=addrutil.c;a=blob_plain'
52 #
53 #  - Change some more strings:
54 #       cat data \
55 #       | sed 's/^Reward: An @GnuPG.*/Reward: m/' \
56 #       | sed 's/^Reward: .*sticker.*/Reward: s/' \
57 #       | sed 's/^Reward: .*tshirt.*/Reward: t/'  \
58 #       | sed 's/^Reward: .*Listed.*/Reward: l/' > newdata
59 #
60 #   cat data | sed 's/^Reward: An @GnuPG.*/Reward: m/' | sed 's/^Reward: .*sticker.*/Reward: s/'| sed 's/^Reward: .*tshirt.*/Reward: t/'  | sed 's/^Reward: .*Listed.*/Reward: l/'
61 #
62 #  - To add a unique ID use this command
63 #
64 #    awk '/^Goteo-ID:/ {cmd="gpg -a --gen-random 0 15 | tr +/ 42"; cmd | getline foo; print "Id: " foo; close(cmd); }; {print}' data >newdata
65 #
66 #  - To finally create the input data
67 #    fields="-FId -FUser -FName -FReward -FMail -FAddress"
68 #     ( ./addrutil -SReward=t $fields data \
69 #      && ./addrutil -SReward=m $fields data) > goteo-collect.input
70 #
71
72
73
74 use CGI;
75 use POSIX qw(strftime);
76 use Fcntl qw(:flock SEEK_END);
77 use MIME::Base32 qw( RFC );
78
79 my $time = strftime "%Y-%m-%d %H:%M:%S", gmtime;
80 my $htdocs = '/var/www/all/accounts.gnupg.net/htdocs/';
81
82 my $q  = new CGI;
83
84 my $id = $q->param("id");
85 my $mode = $q->param("mode");
86 my $address = "";
87 my $txid = "";
88 my $errorstr = "";
89 my $tsize= "";
90
91 sub get_txid {
92     local $data;
93
94     open (DEVRAND, "<", "/dev/urandom");
95     read (DEVRAND, $data, 6);
96     close (DEVRAND);
97     MIME::Base32::encode($data);
98 }
99
100 # Write the collected data out to the log file.  On return
101 # $txid has the transaction id.
102 sub write_logfile {
103     open(LOGFILE, ">>", "/var/log/gnupg.net/goteo-collect")
104         || die "error opening log file: $!";
105     flock(LOGFILE, LOCK_EX) || die "error locking log file: $!";
106     seek(LOGFILE, 0, SEEK_END) || die "error seek to end of log file: $!";
107
108     $txid = &get_txid();
109
110     print LOGFILE "Start: $time\n";
111     print LOGFILE "txid: $txid\n";
112     print LOGFILE "reward: $reward\n";
113     foreach $name ($q->param) {
114         $value = $q->param($name);
115         if ($name !~ /^Start/i) {
116             $value =~ s/\r//g;
117             chomp $value;
118             $value =~ s/\n/\n  /g;
119             print LOGFILE "$name: $value\n";
120         }
121     }
122     print LOGFILE "\n";
123
124     flock(LOGFILE, LOCK_UN) || die "error unlocking log file: $!";
125     close(LOGFILE) || die "error closing log file: $!";
126 }
127
128
129 # Find the item for $id and fill in all numbers.  Return false if not
130 # found.
131 sub find_item {
132     local $tmpid;
133     open(INPUTFILE, "<", "/var/log/gnupg.net/goteo-collect.input")
134         || die "error opening input file: $!";
135     while (<INPUTFILE>) {
136         chomp;
137         ($tmpid, $account, $name, $reward, $mail, $address) = split (/:/);
138         if ($tmpid eq $id) {
139             close(INPUTFILE);
140             $account =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/ge;
141             $name =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/ge;
142             $mail =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/ge;
143             $address =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/ge;
144             return 1;
145         }
146     }
147     close(INPUTFILE);
148     0;
149 }
150
151
152 sub write_template {
153     local $fname = shift;
154     local $indel = 0;
155     local $fulladdress;
156
157
158     if ( "$address" =~ /^$name/ ) {
159         $fulladdress = $address;
160     } else {
161         $fulladdress = "$name\n$address";
162     }
163
164     open TEMPLATE, $htdocs . $fname;
165     while (<TEMPLATE>) {
166         if ($indel) {
167             $indel = 0 if (/<!--END_/);
168             next;
169         }
170         elsif (($reward eq 'm') && /^<!--BEGIN_T_SHIRT/) {
171             $indel = 1;
172             next;
173         }
174         elsif (($reward eq 't') && /^<!--BEGIN_MAIL/) {
175             $indel = 1;
176             next;
177         }
178
179         # Only one replacement allowed to avoid recursive replacements
180         s/\x40ID\x40/$id/g
181         || s/\x40NAME\x40/$name/g
182         || s/\x40ACCOUNT\x40/$account/g
183         || s/\x40ADDRESS\x40/$fulladdress/g
184         || s/\x40MAIL\x40/$mail/g
185         || s/\x40REWARD\x40/$reward/g
186         || s/\x40TXID\x40/$txid/g
187         || s/\x40TSIZE\x40/$tsize/g
188         || s/\x40MAILBOX\x40/$mailbox/g
189         || s/\x40MAILBOX2\x40/$mailbox2/g
190         || s/\x40ERRORSTR\x40/$errorstr/g;
191
192         print;
193     }
194     close TEMPLATE;
195 }
196
197
198 # Write a page with all the data for the goteo account.
199 sub write_main_page {
200     print $q->header(-type=>'text/html', -charset=>'utf-8');
201     print "\n";
202     &write_template("goteo-collect.html.in");
203 }
204
205 sub write_error_page {
206     local $text = shift;
207
208     $errorstr = '<p style="color: red;">' . $text . '</p>';
209     # Keep the entered values.
210     $mail = $q->param('mail');
211     $address = $q->param('address');
212     $mailbox = $q->param('mailbox');
213     $mailbox2 = $q->param('mailbox2');
214     &write_main_page();
215 }
216
217 # Write a page with the collected data
218 sub write_thanks_page {
219     print $q->header(-type=>'text/html', -charset=>'utf-8');
220     print "\n";
221     $mail = $q->param('mail');
222     $address = $q->param('address');
223     $mailbox = $q->param('mailbox');
224     $mailbox2 = $q->param('mailbox2');
225     $tsize    = $q->param('tsize');
226     &write_template("goteo-collect-thx.html.in");
227 }
228
229
230 #
231 # Main
232 #
233 if ($id eq '') {
234     print $q->header('text/html');
235     print $q->start_html('Error');
236     print $q->h1('Bad request - please use the correct URL');
237     print $q->end_html;
238 }
239 elsif (not &find_item()) {
240     print $q->header('text/html');
241     print $q->start_html('Error');
242     print $q->h1('No such URL');
243     print $q->p('Please verify that you used the URL from the mail');
244     print $q->end_html;
245 }
246 elsif ($mode eq 'response') {
247     if ($q->param('mail') !~ /[a-zA-Z0-9]+@[a-zA-Z]+/ ) {
248         write_error_page('Invalid mail address given!');
249     }
250     elsif ($reward eq 't' and $q->param('tsize') !~ /^[SLX]$/ ) {
251         write_error_page('Size of t-shirt not given!');
252     }
253     else {
254         write_logfile();
255         write_thanks_page();
256     }
257 }
258 else {
259     &write_main_page();
260 }