Subversion Repositories PEEPS

Rev

Rev 56 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#!/usr/bin/perl
2
 
3
# Redirect error messages to a log of my choosing. (it's annoying to filter for errors in the shared env)
4
#my $error_log_path = $ENV{SERVER_NAME} eq "volunteers.rollercon.com" ? "/home3/rollerco/logs/" : "/tmp/";
5
#close STDERR;
6
#open STDERR, '>>', $error_log_path.'vorc_error.log' or warn "Failed to open redirected logfile ($0): $!";
7
#warn "Redirecting errors to ${error_log_path}vorc_error.log";
8
 
9
use strict;
10
use PEEPS;
11
use CGI qw/param header start_html url redirect/;
12
use CGI::Cookie;
13
our $h = HTML::Tiny->new( mode => 'html' );
14
my $dbh = getRCDBH ();
4 - 15
$ENV{HTTPS} = 'ON' if $ENV{SERVER_NAME} =~ /^peeps/;
2 - 16
 
17
my $cookie_string = authenticate (1) || die;
18
my ($EML, $PWD, $LVL) = split /&/, $cookie_string;
19
my $user = $ORCUSER;
24 - 20
my $RENEWAL_WINDOW = 90;
2 - 21
#my $activated = $ORCUSER->{access};
22
 
23
use DateTime;
22 - 24
my $dt = DateTime->today()->strftime ('%Y-%m-%d');
2 - 25
 
22 - 26
 
27
## Which Policy ID is being requested?
28
##
29
my $policy_id = WebDB::trim scalar param ("policy") // "ERROR";
30
my $policy = getPolicyByID ($policy_id) // {};
31
if ($policy_id ne $policy->{id} or !$policy->{active}) {
32
  ERROR ("Policy ID [$policy_id] not found",
33
         "It's unclear what type of insurance you're attempting to purchase.",
34
         "Viewed Attestation page without valid policy_id.");
2 - 35
}
36
 
22 - 37
 
38
## We have a valid Policy ID, check purchase eligibility.
39
##
40
my ($eligible, $daysremaining, $active_policy, $league_id, $league_name);
41
 
42
if ($policy->{type} eq "league") {
43
  ## If it's a League Policy Type, then get the Leauge ID too.
44
  ##
45
  $league_id = $policy->{type} eq "league" ? WebDB::trim scalar param ("league") // undef : undef;
46
  $league_name = $league_id =~ /^\d+$/ ? getLeagueName ($league_id) : undef;
47
 
48
  if (!$league_name) {
49
    ## If there's no leauge_name, it's not a valid league...
50
    ERROR ("League ID [$league_id] not found",
51
           "It's unclear which league you are attempting to cover.",
52
           "Viewed Attestation page for league coverage without valid league_id.");
53
  }
54
 
55
  ## Only Leauge Admins should be purchasing league type polcies
50 - 56
  use tableViewer;
57
  if (notInArray ($league_id, isLeagueAdmin ($user->{person_id}))) {
22 - 58
    ERROR ("Not a League Admin [$league_id]",
59
           "You must be a League Admin to purchase insurance for the league.",
60
           "Viewed Attestation page for league coverage but not a league admin.");
61
  }
62
 
31 - 63
  ## Leagues have to be approved to purchase Alcohol Liability coverage
64
  if ($policy->{id} eq "3" and !getLeague ($league_id)->{alcohol_liability_eligible}) {
65
    ERROR ("League Not Eligible [$league_id]",
66
           "You must be pre-approved to purchase Alcohol Liability coverage for the league. Please email insurance\@wftdi.com to begin approval process.",
67
           "Viewed Attestation page for Alchohol Liability coverage but not pre-approved.");
68
  }
69
 
22 - 70
  ## Check to see if this is a new purchase or within the renewal period.  If neither, eligible will be empty.
31 - 71
  $active_policy = isLeagueCovered ($league_id, undef, $policy->{name});
22 - 72
  if ($active_policy) {
73
    $daysremaining = remainingOrgPolicyDays ($league_id, $active_policy);
74
    if ($daysremaining <= $RENEWAL_WINDOW) {
75
      $eligible = "renew";
76
    }
77
  } else {
78
    $eligible = "new";
79
  }
80
} elsif ($policy->{type} eq "personal") {
81
  if ($policy->{id} eq "4") { # They're trying to buy RollerCon Coverage...
82
    $active_policy = isPersonCovered ($user->{id}, '2026-07-11');
83
    if (!$active_policy) {
84
      ($active_policy) = $dbh->selectrow_array ("select id from coverage where policy_id = ? and person_id = ?", undef, 4, $user->{id});
85
    }
86
 
87
    ERROR ("Already Covered",
88
           "You are already covered for RollerCon 2026 by Policy $active_policy. No need to purchase.",
89
           "Attempted to purchase RollerCon 2026 covereage but not needed") unless !$active_policy;
90
 
91
  } else {
92
    ## Check to see if this is a new purchase or within the renewal period.  If neither, eligible will be empty.
93
    $active_policy = isPersonCovered ($user->{id});
94
    if ($active_policy) {
95
      $daysremaining = remainingPolicyDays ($user->{id}, $active_policy);
96
      if ($daysremaining <= $RENEWAL_WINDOW) {
97
        $eligible = "renew";
98
      }
99
    } else {
100
      $eligible = "new";
101
    }
102
  }
103
} else {
104
  ## If we're here, it means the policy type wasn't recognized...
105
  ERROR ("Something weird happened...",
106
         "The type of policy you attempted to puchase doesn't seem to exist.",
107
         "Viewed Attestation page for invalid policy type.");
2 - 108
}
109
 
22 - 110
ERROR ("Not Eligible for Renewal",
111
       "You".($policy->{type} eq "league" ? "r league is" : " are")." currently covered by policy $active_policy, which has $daysremaining days remaining. You can only renew within the last $RENEWAL_WINDOW days of your current policy.",
112
       "Viewed Attestation page but wasn't eligible to renew.") unless $eligible;
113
 
114
## Check to see if there is an abandoned checkout that needs to be completed...
115
my ($abandoned_checkout) = $policy->{type} eq "league" ?
116
      $dbh->selectrow_array ("select url from square_order where organization_id = ? and policy_id = ? and status = ? order by created desc limit 1", undef, $league_id, $policy->{id}, "DRAFT") :
117
      $dbh->selectrow_array ("select url from square_order where person_id = ? and policy_id = ? and status = ? order by created desc limit 1", undef, $user->{id}, $policy->{id}, "DRAFT") ;
2 - 118
if ($abandoned_checkout) {
119
  my $cgi = CGI->new();
22 - 120
  logit ($user->{id}, "Returned to abandoned $policy->{type} policy checkout.");
2 - 121
  print $cgi->redirect ($abandoned_checkout);
122
  exit;
123
}
124
 
22 - 125
## Get the terms for attestion...
126
my @terms = map { @{$_} } @{ $dbh->selectall_arrayref ("select term from attestation where id = ? order by attestation.index", undef, $policy->{attestation_id}) };
2 - 127
my $terms;
22 - 128
foreach (1..scalar @terms) {
2 - 129
  $terms++ if param ("Term".$_);
130
}
131
my $esig = param ("esignature") // "";
132
 
22 - 133
if ($terms == scalar @terms and $esig =~ /^\w+$/) {
2 - 134
  # All of the checkboxes were accepted and an eSignature was entered.
135
  # Create the Square Checkout link and redirect the user there.
22 - 136
  logit ($user->{id}, "Submitted purchase attestation for $policy->{type} $policy->{name} with all terms accepted and esignature entered.");
137
  sendToSquare ($esig, $terms, $policy);
2 - 138
  exit;
139
}
140
 
141
print header (-cookie=>CGI::Cookie->new(-name=>'PEEPSAUTH',-value=>"$cookie_string"));
53 - 142
printRCHeader("Attestation");
2 - 143
 
144
print $h->close ("table");
145
 
146
print $h->open ("form", { name => "Attestation", method => "post", action => url });
147
 
148
print $h->input ( { type => "hidden", name => "timezone", id => "TZFIELD", value => "" } );
22 - 149
print $h->input ( { type => "hidden", name => "policy", value => $policy_id } );
150
print $h->input ( { type => "hidden", name => "league", value => $league_id } ) unless !$league_id;
2 - 151
 
152
 
22 - 153
print $h->div ({ class=>"error" }, "&nbsp;", "ERROR: You must agree to each term to continue.") if $terms and $terms < scalar @terms;
2 - 154
 
53 - 155
print $h->div ({ class=>"index" },[
156
  $h->p ({ class => "heading" }, "Policy Details"),
157
  $h->div ({ class => "rTable", style=>"min-width: 0%;" }, [
158
    map ({ $h->div ({ class => "rTableRow" }, [
54 - 159
      $h->div ({class=>"rTableCellr", style=>"font-size: unset;"}, ucfirst ($_).": "),
56 - 160
      $h->div ({class=>"rTableCellr", style=>"font-size: unset;"}, /fee/ ? '$'.sprintf ('%.2f', $policy->{$_}).' [USD]' : ucfirst ($policy->{$_}))
53 - 161
    ]) } qw/ name type fee /),
57 - 162
    (isWFTDAMember ($user->{id}) and $policy->{member_discount}) ? $h->div ({ class => "rTableRow" }, [ $h->div ({class=>"rTableCellr", style=>"font-size: unset;"}, "Discount: "), $h->div ({class=>"rTableCellr", style=>"font-size: unset;"}, '$'.sprintf ('-%.2f', $policy->{member_discount}).' [USD] WFTDA Member') ]) : undef
53 - 163
  ])
164
]);
2 - 165
 
53 - 166
#print $h->h2 ("Policy Details");
167
#print $h->div ({ style=>"max-width:850px;" }, $h->ul ([$h->li (map { "$_: $policy->{$_}" } keys %{$policy})]));
2 - 168
 
53 - 169
#print $h->ul ([map { $h->li ({ class => "lisp0" }, [
170
#    $h->div ({ class=>"liRight", style=>"margin-right:.5em" }, ucfirst ($_).": "),
171
#    $h->div ({ class=>"liLeft" }, /fee/ ? '$'.sprintf '%.2f', $policy->{$_}.' [USD]' : $policy->{$_} )]) } qw/ name type fee / ]);
22 - 172
 
173
 
53 - 174
 
22 - 175
if ($policy->{type} eq "personal") {
176
  print $h->h2 ("Release and Waiver of Liability");
177
 
178
  print $h->div ({ style=>"max-width:850px;" }, "RELEASE AND WAIVER OF LIABILITY, ASSUMPTION OF RISK, AND INDEMNITY AGREEMENT (\"Agreement\") IN CONSIDERATION of being permitted to participate this date, in any way, at any time, in Women’s Flat Track Roller Derby (\"Activity\"), I, for myself, my personal representatives, assigns, heirs, and next of kin:");
179
 
180
  print $h->ol ({ style=>"max-width:850px;" }, [
181
    $h->li ("ACKNOWLEDGE, agree, and represent that I understand the nature of this Activity, and that I am qualified, in good health, and in proper physical condition to participate in such Activity. I further agree and warrant that if, at any time, I believe the conditions to be unsafe, I will immediately discontinue further participation in this Activity."),
182
    $h->li ("FULLY UNDERSTAND that: (a) THIS ACTIVITY INVOLVES RISKS AND DANGERS OF SERIOUS BODILY INJURY, INCLUDING PERMANENT DISABILITY, PARALYSIS, AND DEATH (\"Risks\"); (b) these Risks and dangers may be caused by my own actions or inactions, the actions or inactions of others participating in the Activity, the conditions in which the Activity takes place, or THE NEGLIGENCE OF THE \"RELEASEES\" NAMED BELOW; (c) there may be OTHER RISKS or SOCIAL AND ECONOMIC LOSSES either not known to me or not readily foreseeable at this time; and I FULLY ACCEPT AND ASSUME ALL SUCH RISKS AND ALL RESPONSIBILITY FOR LOSSES, COSTS, AND DAMAGES I incur as a result of my participation, in the Activity."),
183
    $h->li ("HEREBY RELEASE, DISCHARGE, AND COVENANT NOT TO SUE the sanctioning organization(s), their administrators, directors, agents, officers, members, volunteers, and employees, other participants, officials, rescue personnel, sponsors, advertisers, owners and lessees of Premises on which the Activity is conducted, (each of the forgoing shall be considered one of the RELEASEES herein) FROM ALL LIABILITY, CLAIMS, DEMANDS, LOSSES, OR DAMAGES ON MY ACCOUNT CAUSED, OR ALLEGED TO BE CAUSED, IN WHOLE OR IN PART BY THE NEGLIGENCE OF THE RELEASEES OR OTHERWISE, INCLUDING NEGLIGENT RESCUE OPERATIONS; AND I FURTHER AGREE that if, despite this RELEASE AND WAIVER OF LIABILITY, ASSUMPTION OF RISK, AND INDEMNITY AGREEMENT I, or anyone on my behalf, makes a claim against any of the RELEASEES, I WILL INDEMNIFY, SAVE, AND HOLD HARMLESS EACH OF THE RELEASEES from any litigation expenses, attorney fees, loss, liability, damage, or cost which may be incurred as the result of such claim."),
184
    ]);
185
 
186
  print $h->div ({ style=>"max-width:850px;" }, "I ACKNOWLEDGE THAT I AM OVER THE AGE OF 18 YEARS, HAVE READ THIS AGREEMENT AND FULLY UNDERSTAND ITS TERMS, UNDERSTAND THAT I HAVE GIVEN UP SUBSTANTIAL RIGHTS BY SIGNING IT, HAVE SIGNED IT FREELY AND WITHOUT ANY INDUCEMENT OR ASSURANCE OF ANY NATURE, AND I INTEND IT TO BE A COMPLETE AND UNCONDITIONAL RELEASE OF ALL LIABILITY TO THE GREATEST EXTENT ALLOWED BY LAW AND AGREE THAT IF ANY PORTION OF THIS AGREEMENT IS HELD TO BE INVALID, THE BALANCE, NOTWITHSTANDING, SHALL CONTINUE IN FULL FORCE AND EFFECT.");
187
  print $h->br;
188
}
189
my $t = 1;
190
my @terms = map { $h->div ({ class => "lisp0", style=>"margin-bottom:1em" }, [
191
    $h->div ({ class=>"liLeft" }, $_),
192
    $h->div ({ class=>"liRight", onClick=>"document.forms['Attestation'].elements['Term$t'].click();" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term".$t++, onClick=>"event.stopPropagation();" })])]) } @terms;
193
 
2 - 194
print $h->div ({ style=>"max-width:850px;" }, [
22 - 195
  $h->h3 ($policy->{name}),
196
  @terms,
197
#  $h->div ({ class => "lisp0"}, [
198
#    $h->div ({ class=>"liLeft" }, "I have read and agree with the WFTDA Release and Waiver of Liability, Assumption of Risk, and Indemnity Agreement *Click here to download the Release and Waiver of Liability form."),
199
#    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term1" })])]),
200
#  $h->h3 ("Accidental Medical"),
201
#  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
202
#    $h->div ({ class=>"liLeft" }, "I am 18 or older."),
203
#    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term2" })])]),
204
#  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
205
#    $h->div ({ class=>"liLeft" }, "I am obtaining coverage for myself (I may not acquire coverage on behalf of someone else)."),
206
#    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term3" })])]),
207
#  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
208
#    $h->div ({ class=>"liLeft" }, "My league has WFTDA Insurance. I understand I must obtain the same coverage as my league. If I am not affiliated with a league, I understand coverage is only valid when I skate with a WFTDA insured league."),
209
#    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term4" })])]),
210
#  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
211
#    $h->div ({ class=>"liLeft" }, "I understand in order for insurance coverage to be in effect, I must adhere to the applicable Risk Management Guidelines and/or rules for the activity in which I am participating. Failure to do so will result in denial of claims and may result in revocation of coverage."),
212
#    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term5" })])]),
213
#  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
214
#    $h->div ({ class=>"liLeft" }, "I understand if I am injured, I am responsible to submit an injury report, and must do so within 14 days of the date of my injury. I can request injury reports from insurance\@wftda.com. My league may assist me with this, but ultimately, it is my responsibility. Failure to submit an injury report within the allowable grace period will result in the denial of my claim."),
215
#    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term6" })])]),
216
#  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
217
#    $h->div ({ class=>"liLeft" }, "I understand coverage is non-refundable and non-transferable. Coverage only transfers to other WFTDA Insured leagues."),
218
#    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term7" })])]),
219
#  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
220
#    $h->div ({ class=>"liLeft" }, "I understand reckless or negligent behavior that is outside of the confines of game-related contact, including fighting, punching, kicking, or intentional injury, that puts you or any participant at risk is not tolerated, and is grounds for immediate termination of coverage."),
221
#    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term8" })])]),
2 - 222
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
22 - 223
    $h->div ({ class=>"liLeft" }, "Electronic Signature:&nbsp;&nbsp;".$h->input ({ type => "text", name => "esignature", id => "esig", value => "<enter civil name>", onFocus => "this.value = '';"})),
224
    $h->div ({ class=>"liRight" }, $h->input ({ type => "submit", id=>"submitButton", disabled=>[], onClick => "if (esignature.value == '' || esignature.value == '<enter civil name>') { alert('Please type your civil name in the Electronic Signature box'); document.getElementById('esig').focus(); return false; }" }))]),
2 - 225
 
226
]);
227
 
228
print<<javascript;
229
 
230
<script>
231
  document.addEventListener('DOMContentLoaded', function() {
232
    const checkboxes = document.querySelectorAll('.attest');
233
    const submitButton = document.getElementById('submitButton');
234
 
235
    function checkAllCheckboxes() {
236
        let allChecked = true;
237
        checkboxes.forEach(checkbox => {
238
            if (!checkbox.checked) {
239
                allChecked = false;
240
            }
241
        });
242
        submitButton.disabled = !allChecked;
243
    }
244
 
245
    checkboxes.forEach(checkbox => {
246
        checkbox.addEventListener('change', checkAllCheckboxes);
247
    });
248
 
249
    // Initial check when the page loads
250
    checkAllCheckboxes();
251
  });
252
 
253
  const hiddenField = document.getElementById('TZFIELD');
254
  hiddenField.value = Intl.DateTimeFormat().resolvedOptions().timeZone;
255
</script>
256
 
257
javascript
258
 
259
print $h->close ("form"), $h->close ("body"), $h->close ("html");
260
 
261
 
262
 
263
 
264
sub sendToSquare {
265
  my $esig = shift || return "ERROR: No Signature";
22 - 266
  my $terms = shift // return "ERROR: No Term Count";
267
  my $policy = shift // return "ERROR: No Policy ID";
2 - 268
  my $user_tz = param ("timezone") // 'America/Chicago';
269
 
270
  use REST::Client;
271
  use JSON;
272
  use Data::Dumper;
273
  use UUID::Tiny qw(create_UUID_as_string UUID_V4);
274
 
275
  my $uuid_v4_string = create_UUID_as_string(UUID_V4);
22 - 276
#  my $policy = getPolicyByID (1);
2 - 277
 
278
  my $client = REST::Client->new();
279
  $client->setHost (getSetting ("SQUARE_API_HOST"));
280
 
281
  my $headers = {
282
    "Authorization" => 'Bearer '.getSetting ("SQUARE_AUTH_TOKEN"),
283
    "Square-Version" => "2025-10-16",
284
    "Content-Type" => "application/json",
285
    };
286
 
287
  my $body = {
288
    "idempotency_key" => "$uuid_v4_string",
289
    "checkout_options" => {
22 - 290
      "redirect_url"  => url ( -base => 1 )."/confirmation",
2 - 291
      "enable_coupon" => JSON::false
292
    },
293
#    "quick_pay" => {
294
#      "name" => $policy->{name},
295
#      "price_money" => {
296
#        "amount" => $policy->{fee} * 100,
297
#        "currency" => "USD"
298
#      },
299
#      "location_id" => getSetting ("SQUARE_LOCATION_ID")
300
#    },
301
    "order" => {
302
    	"customer_id" => "$user->{id}",
303
      "location_id" => getSetting ("SQUARE_LOCATION_ID"),
304
      "discounts"   => isWFTDAMember ($user->{id}) ? [{
305
        "name"  => "WFTDA Member Discount",
306
        "scope" => "ORDER",
307
#        "type" => "FIXED_AMOUNT",
308
        "amount_money" => {
22 - 309
#          "amount"   => getSetting ("WFTDA_MEMBER_DISCOUNT") * 100,
310
          "amount"   => $policy->{member_discount} * 100,
2 - 311
          "currency" => "USD"
312
        }
313
      }] : [],
314
      "line_items" => [{
315
        "name" => $policy->{name},
316
        "quantity" => "1",
317
        "base_price_money" => {
318
          "amount" => $policy->{fee} * 100,
319
          "currency" => "USD"
320
        },
321
      }]
322
    },
323
    "payment_note" => $user_tz
324
  };
325
  my $json_body = encode_json $body;
326
 
327
  $client->POST(
328
    '/v2/online-checkout/payment-links',
329
    $json_body,
330
    $headers
331
  );
332
  my $response = from_json($client->responseContent());
333
 
22 - 334
  warn '/v2/online-checkout/payment-links/'.$response->{payment_link}->{id};
335
  $body->{payment_link}->{checkout_options}->{redirect_url} = url ( -base => 1 )."/confirmation?order_id=".$response->{payment_link}->{order_id};
336
  $body->{payment_link}->{version} = $response->{payment_link}->{version};
337
  $json_body = encode_json $body;
338
  $client->PUT(
339
    '/v2/online-checkout/payment-links/'.$response->{payment_link}->{id},
340
    $json_body,
341
    $headers
342
  );
343
  my $response2 = from_json($client->responseContent());
344
 
345
 
346
  warn Dumper($response2);
347
 
2 - 348
#  warn $response->{payment_link}->{url};
349
 
350
  $response->{payment_link}->{created_at} =~ s/T/ /;
351
  $response->{payment_link}->{created_at} =~ s/Z$//;
352
 
353
  $dbh->do ("insert into square_order
22 - 354
             (square_id, order_id, person_id, organization_id, policy_id, url, idempotency_key, created, user_ip, amount, status, attestation)
355
             values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", undef,
2 - 356
             $response->{payment_link}->{id},
357
             $response->{payment_link}->{order_id},
358
             $user->{id},
22 - 359
             $league_id,
360
             $policy->{id},
2 - 361
             $response->{payment_link}->{url},
362
             $uuid_v4_string,
363
             $response->{payment_link}->{created_at},
364
             $ENV{REMOTE_ADDR},
365
             $policy->{fee},
366
             $response->{related_resources}->{orders}->[0]->{state},
367
             $terms." + ".$esig
368
           ) unless !$response->{payment_link}->{id};
369
 
370
  my $cgi = CGI->new();
371
  logit ($user->{id}, "Redirected to Square for payment");
372
  print $cgi->redirect ($response->{payment_link}->{url});
373
 
374
  exit;
5 - 375
}
22 - 376
 
377
sub ERROR {
378
  my $header = shift // "Unknown Error";
379
  my $text   = shift // "Something unexpectedly bad happened.";
380
  my $logmsg = shift // "Unknown Error happened while viewing the Attestation page";
381
 
382
  print header (-cookie=>CGI::Cookie->new(-name=>'PEEPSAUTH',-value=>"$cookie_string"));
383
  printRCHeader("Atttestation");
384
  print $h->close ("table");
385
  print $h->h2 ($header);
386
  print $h->div ({ style=>"max-width:450px;" }, $text, "&nbsp;");
387
  print $h->button ({onclick => "window.location.href='/';"}, "Home");
388
  print $h->close ("BODY", "HTML");
389
  logit ($user->{id}, $logmsg);
390
  exit;
391
}