web: Add new donation system
authorWerner Koch <wk@gnupg.org>
Mon, 26 May 2014 15:05:59 +0000 (17:05 +0200)
committerWerner Koch <wk@gnupg.org>
Mon, 26 May 2014 15:05:59 +0000 (17:05 +0200)
--

We now use Stripe.com for credit card processing.  This required quite
some work on our site for proper and not too privicy intrusive
payments.

To make the system work the Payproc at
 git://git.gnupg.org/payproc.git
needs to be installed.

cgi/config.rc [new file with mode: 0644]
cgi/procdonate.cgi [new file with mode: 0755]
web/donate/checkout-cc.org [new file with mode: 0644]
web/donate/checkout.org [new file with mode: 0644]
web/donate/donate-thanks.org [new file with mode: 0644]
web/donate/error.org [new file with mode: 0644]
web/donate/index.org [new file with mode: 0644]
web/share/gnupg-badge-128x128.png [new file with mode: 0644]
web/share/site.css

diff --git a/cgi/config.rc b/cgi/config.rc
new file mode 100644 (file)
index 0000000..64290f2
--- /dev/null
@@ -0,0 +1,7 @@
+# config.rc - Configuration variables for all CGIs         -*- perl -*-
+
+htdocs  => '/var/www/www/www.gnupg.org/htdocs/',
+
+payprocd_socket => '/var/run/payproc/daemon',
+
+#eof#
diff --git a/cgi/procdonate.cgi b/cgi/procdonate.cgi
new file mode 100755 (executable)
index 0000000..664ba8c
--- /dev/null
@@ -0,0 +1,487 @@
+#!/usr/bin/perl -T
+
+# procdonate.cgi - Donation payment processor for gnupg.org
+# Copyright (C) 2014 g10 Code GmbH
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+
+use strict;
+use CGI;
+use Cwd qw(realpath);
+use IO::Socket::UNIX;
+
+realpath($0) =~ /^(.*)\/.*$/;
+my %config = do $1 . '/config.rc';
+
+my $htdocs =  $config{htdocs};
+my $socket_name = $config{payprocd_socket};
+my $error_marker = '<span style="color: red;">* error</span>';
+
+# The form variabales are accessed via Q.
+my $q  = new CGI;
+
+# This is a multi-purpose CGI.  The mode decides what to do.
+my $mode = $q->param("mode");
+my $sessid = $q->param("sessid");
+
+# Variables used in the template pages.
+my $amount = "";
+my $stripeamount = "";
+my $currency = "";
+my $name = "";
+my $mail = "";
+my $message = "";
+my $errorstr = "";
+
+# We use a dictionary to track error.  Those errors will then be
+# inserted into the output by write_template.
+my %errdict = ();
+
+# Prototypes
+sub fail ($);
+
+
+# Write a template file.  A template is a proper HTML file with
+# variables enclosed in HTML comments.  To allow inserting data into
+# a value attribute of an input field, such a tag needs to be written as
+#   <input value=""/><!--FOO-->
+# the result after processing will be
+#   <input value="foo"/>
+# assuming that the value of FOO is foo. Note that this substitution
+# rules work for all tags and thus you better take care to add an
+# extra space if if do not want this to happen.
+sub write_template ($) {
+    my $fname = shift;
+
+    my $errorpanel = '';
+    my $err_amount = '';
+    my $err_name = '';
+    my $err_mail = '';
+    my $checkother = ' checked="checked"';
+    my $sel_eur = '';
+    my $sel_usd = '';
+    my $sel_gbp = '';
+    my $sel_jpy = '';
+    my $message_fmt;
+
+    # Avoid broken HTML attributes.
+    $amount =~ s/\x22/\x27/g;
+    $stripeamount =~ s/\x22/\x27/g;
+    $currency =~ s/\x22/\x27/g;
+    $name =~ s/\x22/\x27/g;
+    $mail =~ s/\x22/\x27/g;
+    $message =~ s/\x22/\x27/g;
+
+    # Clean possible user provided data
+    $sessid =~ s/</\x26lt;/g;
+    $amount =~ s/</\x26lt;/g;
+    $stripeamount =~ s/</\x26lt;/g;
+    $currency =~ s/</\x26lt;/g;
+    $name =~ s/</\x26lt;/g;
+    $mail =~ s/</\x26lt;/g;
+    $message =~ s/</\x26lt;/g;
+
+    # Create a formatted message.
+    $message_fmt = $message;
+    $message_fmt =~ s/\n/<br\x2f>/g;
+    print STDERR "selected currecny->$currency<-\n";
+    if ( $currency =~ /EUR/i ) {
+        $sel_eur = ' selected="selected"';
+    } elsif ( $currency =~ /USD/i ) {
+        $sel_usd = ' selected="selected"';
+    } elsif ( $currency =~ /GBP/i ) {
+        $sel_gbp = ' selected="selected"';
+    } elsif ( $currency =~ /JPY/i ) {
+        $sel_jpy = ' selected="selected"';
+    }
+    print STDERR "selected currecny->$sel_gbp<-\n";
+
+    # Build error strings.
+    foreach (keys %errdict)
+    {
+        if    (/amount/) { $err_amount = $error_marker; }
+        elsif (/name/)   { $err_name   = $error_marker; }
+        elsif (/mail/)   { $err_mail   = $error_marker; }
+
+        $errorpanel = $errorpanel . "Field $_: " . $errdict{$_} . "<br/>\n"
+    }
+    if ( $errorpanel ne '' )
+    {
+        $errorpanel =
+            "<div style='color: red;'><p>\n" . $errorpanel . "</p></div>\n";
+    }
+
+    open TEMPLATE, $htdocs . $fname;
+    while (<TEMPLATE>) {
+        if ( /<!--/ )
+        {
+            # Only one replacement per line allowed to avoid recursive
+            # replacements. Note that MESSAGE uses a special treatment
+            # for the textarea tag.
+            s/<!--SESSID-->/$sessid/
+            || s/(\x22\x2f>)?<!--AMOUNT-->/$amount\1/
+            || s/(\x22\x2f>)?<!--STRIPEAMOUNT-->/$stripeamount\1/
+            || s/(\x22\x2f>)?<!--CURRENCY-->/$currency\1/
+            || s/(\x22\x2f>)?<!--NAME-->/$name\1/
+            || s/(\x22\x2f>)?<!--MAIL-->/$mail\1/
+            || s/\x2f><!--CHECKOTHER-->/$checkother\x2f>/
+            || s/(<\x2ftextarea>)?<!--MESSAGE-->/$message\1/
+            || s/<!--MESSAGE_FMT-->/$message_fmt/
+            || s/(<selected=\x22selected\x22)?><!--SEL_EUR-->/$sel_eur>/
+            || s/(<selected=\x22selected\x22)?><!--SEL_USD-->/$sel_usd>/
+            || s/(<selected=\x22selected\x22)?><!--SEL_GBP-->/$sel_gbp>/
+            || s/(<selected=\x22selected\x22)?><!--SEL_JPY-->/$sel_jpy>/
+            || s/<!--ERRORSTR-->/$errorstr/
+            || s/<!--ERR_AMOUNT-->/$err_amount/
+            || s/<!--ERR_NAME-->/$err_name/
+            || s/<!--ERR_MAIL-->/$err_mail/
+            || s/<!--ERRORPANEL-->/$errorpanel/;
+        }
+        print;
+    }
+    close TEMPLATE;
+    $errorstr = "";
+}
+
+
+# Call the payment processor daemon.  Takes the command and a
+# reference to a dictionary with the data as input.  On return that
+# disctionary is replaced by the response data.
+sub payproc ($$)
+{
+    my $cmd = shift;
+    my $data = shift;
+    my $sock;
+    my $key;
+    my $value;
+    my $status;
+    my $rest;
+
+    # print STDERR "calling payproc: ", $cmd, "<-\n";
+
+    $sock = IO::Socket::UNIX->new($socket_name)
+        or fail "socket: $!";
+    $sock->print ($cmd, "\n");
+
+    while (($key,$value) = each %$data) {
+        next if $key =~ /^_/;
+        $value =~ s/\n/\n /g;
+        $sock->print ("$key: $value\n");
+        # print STDERR "  $key: $value\n";
+    }
+    $sock->print ("\n");
+    $sock->flush or fail "write socket: $!";
+
+    %$data = ();
+    while (defined (my $line = <$sock>))
+    {
+        next if $line =~ /^\#/;
+        chomp $line;
+        last if $line eq '';
+        if (not defined $status)
+        {
+            ($status, $rest) = split(' ', $line, 2);
+            if ( $status eq 'ERR' )
+            {
+                $rest =~ /\d+\s+\((.*)\).*/;
+                $$data{"ERR_Description"} = $1;
+            }
+        }
+        elsif ( $line =~ /^\s+/ )
+        {
+            fail "bad dict line received" if not defined $key;
+            $$data{$key} .= "\n" . substr($line, 1);
+        }
+        else
+        {
+            ($key, $value) = split(':', $line, 2);
+            $value =~ s/^\s+//;
+            $$data{$key} = $value;
+        }
+    }
+
+    #print STDERR "payproc status: $status (", $$data{"ERR_Description"}, ")\n";
+    #while (($key,$value) = each %$data) {
+    #     print STDERR "  ", $key, ": ", $value, "\n";
+    #}
+
+    $sock->close;
+    return 1 if $status eq 'OK';
+    return 0 if $status eq 'ERR';
+    fail 'payproc did not return a proper status code';
+}
+
+
+# Write a page with all the data inserted.
+sub write_overload_page ()
+{
+    print $q->header(-type=>'text/html', -charset=>'utf-8');
+    print "\n";
+    $errorstr =
+        '<p>The system is currently processing too many requests.</p>'
+        . '<p>Please retry later.</p>';
+
+    &write_template("donate/error.html");
+}
+
+
+# Write an internal error page
+sub fail ($)
+{
+    my $desc = shift;
+
+# FIXME: write the detailed error only to the log.
+    print $q->header(-type=>'text/html', -charset=>'utf-8');
+    print "\n";
+    $errorstr =
+        '<p>An internal error occured:</p>'
+        . "<p>$desc</p>";
+
+    write_template("donate/error.html");
+    exit 0;
+}
+
+
+# Write a the initial donation page.  This is usallay done to show
+# errors.  The page is intially shown as static page.
+sub write_main_page ()
+{
+    print $q->header(-type=>'text/html', -charset=>'utf-8');
+    print "\n";
+    write_template("donate/index.html");
+}
+
+
+# Write a page with all the data inserted.
+sub write_checkout_page ()
+{
+    print $q->header(-type=>'text/html', -charset=>'utf-8');
+    print "\n";
+    write_template("donate/checkout.html");
+}
+
+# Write a page with all the data inserted specific for cards.
+sub write_checkout_cc_page ()
+{
+    print $q->header(-type=>'text/html', -charset=>'utf-8');
+    print "\n";
+    write_template("donate/checkout-cc.html");
+}
+
+
+# Write the final thank you page.
+sub write_thanks_page ()
+{
+    print $q->header(-type=>'text/html', -charset=>'utf-8');
+    print "\n";
+    write_template("donate/donate-thanks.html");
+}
+
+
+# Check the values entered at the donation page.  Return true if
+# everything is alright.  On error the donation page is send again.
+sub check_donation ()
+{
+    my %data;
+    my $anyerr = 0;
+
+    # Note: When re-displaying the page we always use amount other
+    # because that is easier to implement than figuring out which
+    # amount and currency was used and check the appropriate radio
+    # button.
+    $amount = $q->param("amount");
+    if ($amount eq 'other') {
+      $amount = $q->param("amountother");
+      $currency = $q->param("currency");
+    } else {
+      $currency = 'EUR';
+    }
+    $name = $q->param("name");
+    $name = 'Anonymous' if $name eq '';
+    $mail = $q->param("mail");
+    $message = $q->param("message");
+    $stripeamount = "0";
+
+    # Check the amount.
+    $data{"Amount"} = $amount;
+    $data{"Currency"} = $currency;
+    if (not payproc ('CHECKAMOUNT', \%data )) {
+        $errdict{"amount"} = $data{"ERR_Description"};
+        $anyerr = 1;
+    }
+    $stripeamount = $data{"_amount"};
+    $amount = $data{"Amount"};
+    $currency = $data{"Currency"};
+
+    # Check the mail address
+    if ($mail ne '' and $mail !~ /\S+@\S+\.\S+/ ) {
+        $errdict{"mail"} = 'invalid mail address';
+        $anyerr = 1;
+    }
+
+    # If needed present errors and ask again.  */
+    if ($anyerr) {
+        write_main_page();
+        return;
+    }
+
+
+    # Now create a session.
+    $data{"Stripeamount"} = $stripeamount;
+    $data{"Name"} = $name;
+    $data{"Mail"} = $mail;
+    $data{"Message"} = $message;
+    payproc ('SESSION create', \%data ) or fail $data{"ERR_Description"};
+    $sessid = $data{"_SESSID"};
+
+    # Send the checkout page.
+    write_checkout_page();
+}
+
+# This simply resends the main page again.
+sub resend_main_page ()
+{
+    my %data;
+
+    payproc ('SESSION get ' . $sessid, \%data) or fail $data{"ERR_Description"};
+    $amount = $data{"Amount"};
+    $currency = $data{"Currency"};
+    $stripeamount = $data{"Stripeamount"};
+    $name = $data{"Name"};
+    $mail = $data{"Mail"};
+    $message = $data{"Message"};
+
+    write_main_page();
+}
+
+
+# This simply resends the checkout options page.
+sub resend_card_checkout ()
+{
+    my %data;
+
+    payproc ('SESSION get ' . $sessid, \%data) or fail $data{"ERR_Description"};
+    $amount = $data{"Amount"};
+    $currency = $data{"Currency"};
+    $stripeamount = $data{"Stripeamount"};
+    $name = $data{"Name"};
+    $mail = $data{"Mail"};
+    $message = $data{"Message"};
+
+    write_checkout_page();
+}
+
+
+
+# This simply sends the card specific checkout page.
+sub prepare_card_checkout ()
+{
+    my %data;
+
+    payproc ('SESSION get ' . $sessid, \%data) or fail $data{"ERR_Description"};
+    $amount = $data{"Amount"};
+    $currency = $data{"Currency"};
+    $stripeamount = $data{"Stripeamount"};
+    $mail = $data{"Mail"};
+
+    write_checkout_cc_page();
+}
+
+
+# This is called by FIXME
+sub complete_stripe_checkout ()
+{
+    my %data;
+    my %stripe;
+
+    # fixme: Change the error message to note that the card has not
+    # been charged.  Somehow delete the token
+    payproc ('SESSION get ' . $sessid, \%data) or fail $data{"ERR_Description"};
+
+    # Do the checkout.
+    $stripe{"Card-Token"} = $q->param("stripeToken");
+    $stripe{"Currency"} = $data{"Currency"};
+    $stripe{"Amount"} = $data{"Amount"};
+    $stripe{"Desc"} =
+        "GnuPG donation by " . $data{"Name"} . " <" . $data{"Mail"} . ">";
+    $stripe{"Stmt-Desc"} = "GnuPG donation";
+    $stripe{"Email"} = $q->param("stripeEmail");
+    if ($data{"Mail"} ne $q->param("stripeEmail")) {
+        $stripe{"Meta[mail]"} = $data{"Mail"};
+    }
+    if ($data{"Message"} ne '') {
+        $stripe{"Meta[message]"} = $data{"Message"};
+    }
+    if (not payproc ('CHARGECARD', \%stripe)) {
+        $errorstr =
+            '<p>Error: ' . $stripe{"failure"} . '</p><p>'
+            . $stripe{"failure-mesg"} . '</p>';
+        # Again.
+        prepare_card_checkout ();
+        return;
+    }
+
+    # Print thanks
+
+    $message = <<EOF;
+Amount ..: $stripe{"Amount"} $stripe{"Currency"}
+Desc ....: $stripe{"Desc"}
+Cardno...: *$stripe{"Last4"}
+Processor: Stripe
+Email ...: $stripe{"Email"}
+Charge-Id: $stripe{"Charge-Id"}
+Timestamp: $stripe{"_timestamp"}
+EOF
+    if ($stripe{"Live"} eq 'f') {
+        $message = $message . "\n!!! TEST TRANSACTION !!!";
+    }
+
+    write_thanks_page ();
+    payproc ('SESSION destroy ' . $sessid, ());
+}
+
+
+
+
+
+#
+# Main
+#
+print STDERR "CGI called with mode=$mode\n";
+print STDERR "CGI called with sessid=$sessid\n";
+if ($q->param('url') ne '') {
+    # If the URL field has been filled out, the client did not follow
+    # the instructions and thus failed the Turing test.  Provide an
+    # innocent error page.
+    write_overload_page ()
+}
+elsif ($mode eq 'main') {
+    # Returning from the donation start page
+    check_donation();
+}
+elsif ($mode eq 're-main') {
+    # Returning from the donation start page
+    resend_main_page();
+}
+elsif ($mode eq 're-checkout') {
+    # Redisplay the checkout option page
+    resend_card_checkout();
+}
+elsif ($mode eq 'checkout-cc') {
+    # The checkout page requested a card checkout.
+    prepare_card_checkout();
+}
+elsif ($mode eq 'checkout-stripe') {
+    # we have the stripe token - charge the card.
+    complete_stripe_checkout();
+}
+else {
+    fail('Internal error: Unknown mode');
+}
diff --git a/web/donate/checkout-cc.org b/web/donate/checkout-cc.org
new file mode 100644 (file)
index 0000000..06ee673
--- /dev/null
@@ -0,0 +1,61 @@
+#+TITLE: GnuPG - Donate - Checkout with card
+#+STARTUP: showall
+#+SETUPFILE: "../share/setup.inc"
+
+* Donate - Checkout with card
+
+  You are about to donate
+  @@html:<!--AMOUNT-->@@
+  @@html:<!--CURRENCY-->@@
+  to the GnuPG project using your credit card.
+
+#+BEGIN_HTML
+  <noscript>
+    <p>
+      <strong>Please enable Javascript.</strong>
+    </p>
+    <p id="smallnote">
+       Right, for security reasons it is in general preferable to
+       disable Javascript in a browser.  However, we do not want
+       to handle credit card numbers ourselves and use a service of
+       our payment processor to convey this sensitive information
+       directly between your browser and them.  This requires that
+       you enable enable Javascript for <emph>gnupg.org</emph>
+       and <emph>stripe.com</emph>.
+    </p>
+  </noscript>
+
+
+  <!--ERRORSTR-->
+  <p>
+    <form action="/cgi-bin/procdonate.cgi" method="POST">
+      <input type="hidden" name="mode" value="checkout-stripe">
+      <input type="hidden" name="sessid" value="<!--SESSID-->">
+      <script
+        src="https://checkout.stripe.com/checkout.js"
+        class="stripe-button"
+        data-key="pk_live_lcfUUC9FLdguvgEKqMeaeuWY"
+        data-image="/share/gnupg-badge-128x128.png"
+        data-name="GnuPG"
+        data-description="Donation to the GnuPG project"
+        data-amount="<!--STRIPEAMOUNT-->"
+        data-currency="<!--CURRENCY-->"
+        data-panel-label="Donate {{amount}} to GnuPG"
+        data-label="Donate now"
+      >
+      </script>
+    </form>
+  </p>
+#+END_HTML
+# Note: We do not want to send a
+#         data-email="<!-- MAIL -->"
+#       line to Stripe so to enable the user to use a
+#       a different nail address for use with them.
+
+#+BEGIN_HTML
+  <form action="/cgi-bin/procdonate.cgi" method="POST">
+    <input type="hidden" name="mode" value="re-checkout">
+    <input type="hidden" name="sessid" value="<!--SESSID-->">
+    <input type="submit" value="Back to payment options" />
+  </form>
+#+END_HTML
diff --git a/web/donate/checkout.org b/web/donate/checkout.org
new file mode 100644 (file)
index 0000000..9c5bab8
--- /dev/null
@@ -0,0 +1,100 @@
+#+TITLE: GnuPG - Donate - Checkout
+#+STARTUP: showall
+#+SETUPFILE: "../share/setup.inc"
+
+* Donate - Checkout
+
+  Information on your intended donation:
+
+#+BEGIN_HTML
+  <table border="0" cellpadding="0" cellspacing="4" id="checkoutSummary">
+   <tr>
+     <td align="right">Amount:</td>
+     <td><!--AMOUNT-->
+         <!--CURRENCY--></td>
+   </tr>
+   <tr>
+     <td align="right">Name:</td>
+     <td><!--NAME--></td>
+   </tr>
+   <tr>
+     <td align="right">Mail:</td>
+     <td><!--MAIL--></td>
+   </tr>
+   <tr>
+     <td align="right" valign="top">Message:</td>
+     <td><!--MESSAGE_FMT--></td>
+   </tr>
+  </table>
+#+END_HTML
+
+  If something is wrong, please use the back button below to change
+  it.  If the data is correct, you may proceed by choosing one of the
+  payment options below.
+
+
+  - Donate with a credit card
+
+#+BEGIN_HTML
+   <p id="smallnote">
+      For privacy reasons a click on the button below will take you to a
+      dedicated page for the credit card based checkout.
+   </p>
+   <p>
+      <form action="/cgi-bin/procdonate.cgi" method="POST">
+        <input type="hidden" name="mode" value="checkout-cc">
+        <input type="hidden" name="sessid" value="<!--SESSID-->">
+        <input type="image" src="https://gnupg.org/share/btn-donate.png"
+               border="0" name="submit" alt="Donate with credit card"
+                          title="Donate with credit card">
+      </form>
+    </p>
+#+END_HTML
+
+
+  - Donate using a Paypal account
+
+
+#+HTML: <p id="smallnote">Coming soon (not yet available)</p>
+
+# #+BEGIN_HTML
+#    <p>
+#     <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+#       <input type="hidden" name="cmd" value="_s-xclick">
+#       <input type="hidden" name="hosted_button_id" value="X6PJPV43S58CW">
+#       <input type="image" src="https://gnupg.org/share/btn-donate.png"
+#            border="0" name="submit" alt="Donate using PayPal"
+#                                   title="Donate using PayPal">
+#     </form>
+#   </p>
+# #+END_HTML
+#
+
+  - Donate using a SEPA bank transfer
+
+#+HTML: <p id="smallnote">Coming soon (not yet available)</p>
+
+# #+BEGIN_HTML
+#   <p id="smallnote">
+#     A SEPA bank transfer is possible in most European countries.  We
+#     will send you an account number and you simply wire the money to
+#     that account.
+#     <form action="/cgi-bin/procdonate.cgi" method="POST">
+#       <input type="hidden" name="mode" value="checkout-sepa">
+#       <input type="hidden" name="sessid" value="<!--SESSID-->">
+#       <input type="image" src="https://gnupg.org/share/btn-donate.png"
+#          border="0" name="submit" alt="Donate using SEPA"
+#                                 title="Donate using SEPA">
+#     </form>
+#   </p>
+# #+END_HTML
+
+
+
+#+BEGIN_HTML
+  <form action="/cgi-bin/procdonate.cgi" method="POST">
+    <input type="hidden" name="mode" value="re-main">
+    <input type="hidden" name="sessid" value="<!--SESSID-->">
+    <input type="submit" value="Back to donation page" />
+  </form>
+#+END_HTML
diff --git a/web/donate/donate-thanks.org b/web/donate/donate-thanks.org
new file mode 100644 (file)
index 0000000..c30f94f
--- /dev/null
@@ -0,0 +1,27 @@
+#+TITLE: GnuPG - Donate - Thank you
+#+STARTUP: showall
+#+SETUPFILE: "../share/setup.inc"
+
+* Donate - Thank you
+
+  *Thank you very much for your donation to our work on GnuPG.*
+
+  We will update the list of donors once a week, thus you won’t see
+  your name immediately.  If you did not give a name you won’t be
+  listed at all.
+
+  Here is our transaction data of your payment:
+#+BEGIN_HTML
+  <pre id="checkoutSummary">
+  <!--MESSAGE-->
+  </pre>
+#+END_HTML
+
+  Your credit card statement should list this donation as /GnuPG
+  donation/. If you have any questions please contact /donations/ at
+  /gnupg.org/.
+
+
+#+BEGIN_HTML
+  <p><a href="/index.html">Continue</a></p>
+#+END_HTML
diff --git a/web/donate/error.org b/web/donate/error.org
new file mode 100644 (file)
index 0000000..6780e3e
--- /dev/null
@@ -0,0 +1,9 @@
+#+TITLE: GnuPG - Donate - Error
+#+STARTUP: showall
+#+SETUPFILE: "../share/setup.inc"
+
+* Donate
+
+#+BEGIN_HTML
+  <!--ERRORSTR-->
+#+END_HTML
diff --git a/web/donate/index.org b/web/donate/index.org
new file mode 100644 (file)
index 0000000..5d74af2
--- /dev/null
@@ -0,0 +1,121 @@
+#+TITLE: GnuPG - Donate
+#+STARTUP: showall
+#+SETUPFILE: "../share/setup.inc"
+
+* Donate
+
+  Maintaining and improving GnuPG is costly. For more than 10 years
+  now, [[https://g10code.com][g10^code]], a German company owned and headed by GnuPG's
+  principal author Werner Koch, is bearing the majority of these
+  costs. To help them carry on this work, they need your support.
+
+** Ways to donate
+
+   Paying using a credit card is currently our preferred choice.  [[https://en.wikipedia.org/wiki/Single_Euro_Payments_Area][SEPA]]
+   payments are acceptable but we have not yet automated this process.
+   If you have a Paypal account you may use that too.
+
+   Because the GnuPG projects is not tax exempted, we are not able to
+   send you a respective donation receipt.  If you are company,
+   [[https://g10code.com][g10^code]] can sell you a support contract for GnuPG or provide other
+   kind of paid services.
+
+** Donation form
+
+  To process your donation we need to collect some information.  This
+  information is only used for the purpose of the donation and not
+  send to any other entity not directly involved in the donation
+  process.  Not giving a name makes the donation “anonymous” in that
+  the name won’t be listed on the public thank you page.
+
+#+BEGIN_HTML
+  <!--ERRORPANEL-->
+
+  <form action="/cgi-bin/procdonate.cgi" method="post">
+   <input type="hidden" name="mode" value="main">
+   <p class="ii">Keep this field clear:
+                 <input type="text" size="40" name="url"></p>
+   <table border="0" cellpadding="0" cellspacing="4">
+    <tr>
+      <td></td>
+      <td>How much do you want to donate?</td>
+    </tr>
+    <tr>
+      <td align="right">Amount:</td>
+      <td>
+          <input type="radio" name="amount" value="500"/>500 EUR
+          <input type="radio" name="amount" value="200"/>200 EUR
+          <input type="radio" name="amount" value="100"/>100 EUR
+          <input type="radio" name="amount" value="50"/>50 EUR
+          <input type="radio" name="amount" value="20"/>20 EUR
+          <input type="radio" name="amount" value="5"/>5 EUR
+      </td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>
+          <input type="radio" name="amount"
+                              value="other"/><!--CHECKOTHER-->other:
+          <input type="text"  size="6" name="amountother"
+                              value=""/><!--AMOUNT-->
+          <select name="currency" size="1">
+            <option value="EUR" selected="selected"><!--SEL_EUR-->Euro</option>
+            <option value="USD" ><!--SEL_USD-->US Dollar</option>
+            <option value="GBP" ><!--SEL_GBP-->British Pound</option>
+            <option value="JPY" ><!--SEL_JPY-->Yen</option>
+          </select>
+          <!--ERR_AMOUNT-->
+      </td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>
+          If you want to be listed on the sponsors page, please enter
+          your name as it shall appear there.
+      </td>
+    </tr>
+    <tr>
+      <td align="right">Name:</td>
+      <td>
+          <input type="text" size="40" style="width:200px" name="name"
+                 value=""/><!--NAME-->
+          <!--ERR_NAME-->
+      </td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>
+          In case of payment problems we may want to contact you, please
+          enter your mail address.
+      </td>
+    </tr>
+    <tr>
+      <td align="right">Mail:</td>
+      <td>
+          <input type="text" size="40" style="width:200px" name="mail"
+                   value=""/><!--MAIL--> (optional)
+           <!--ERR_MAIL-->
+      </td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>
+          If you want to leave a message for us, please enter it here:
+      </td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>
+          <textarea cols="40" rows="4" style="width:500px" name="message"
+                    ></textarea><!--MESSAGE-->
+      </td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>
+          <input type="submit" value="Proceed to payment options" />
+      </td>
+    </tr>
+   </table>
+  </form>
+#+END_HTML
diff --git a/web/share/gnupg-badge-128x128.png b/web/share/gnupg-badge-128x128.png
new file mode 100644 (file)
index 0000000..5116ec8
Binary files /dev/null and b/web/share/gnupg-badge-128x128.png differ
index 1e9237d..04a9a3a 100644 (file)
@@ -96,6 +96,11 @@ div.urgent {
 }
 
 
+.ii {
+  display: none !important;
+}
+
+
 /*
    Other elements as commonly used by org-mode
  */
@@ -258,6 +263,7 @@ div.outline-text-3 {
 #cpyright {
     font-style: italic;
     font-size: 0.6em;
+    padding-top: 4em;
 }
 
 #smallnote {
@@ -279,6 +285,11 @@ div.outline-text-3 {
 }
 
 
+#checkoutSummary {
+    background-color: #f0f0f0;
+}
+
+
 .articleRight {
     float: right;
     padding: 2%;