Diff -- /var/www/vhosts/3dshawn.com/ptmatrix.3dshawn.com/unsubscribe.cgi
Diff

/var/www/vhosts/3dshawn.com/ptmatrix.3dshawn.com/unsubscribe.cgi

added on local at 2026-07-01 12:35:16

Added
+133
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to d72bed6f1fe1
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1#!/usr/bin/perl
2
3##################################################################################################################################
4# ______ ____ ____ ______ ______ ____ ___ __ ___ ______ _ __ ____ ____ __ __ _ __ _____ ____
5# / ____// __ \ / __ \ / ____/ / ____// __ \ / | / |/ // ____/| | / // __ \ / __ \ / //_/ | | / /|__ / / __ \
6# / / / / / // / / // __/ / /_ / /_/ // /| | / /|_/ // __/ | | /| / // / / // /_/ // ,< | | / / /_ < / / / /
7# / /___ / /_/ // /_/ // /___ / __/ / _, _// ___ | / / / // /___ | |/ |/ // /_/ // _, _// /| | | |/ / ___/ /_ / /_/ /
8# \____/ \____//_____//_____/ /_/ /_/ |_|/_/ |_|/_/ /_//_____/ |__/|__/ \____//_/ |_|/_/ |_| |___/ /____/(_)\____/
9#
10# - Written by: Shawn Pickering
11# - shawn@shawnpickering.com
12##################################################################################################################################
13use strict;
14use lib '/var/www/vhosts/3dshawn.com/ptmatrix.3dshawn.com';
15
16
17#############################################################
18## Variables
19#############################################################
20
21
22
23############################################################
24# Modules
25############################################################
26use CGI; my $query = new CGI; my $form = $query->Vars;
27use MODS::PTMatrix::Urls; my $getlist = new MODS::PTMatrix::Urls; my $url = $getlist->urls();
28use MODS::DBConnect; my $db = new MODS::DBConnect;
29use MODS::PTMatrix::Config; my $config = new MODS::PTMatrix::Config; my $database_name = $config->settings('database_name');
30
31
32
33#############################################################
34## Get form data
35#############################################################
36foreach my $line(keys %$form){
37 $form->{$line} =~ s/[^!-~\s]//g;
38 $form->{$line} = quotemeta("$form->{$line}");
39}
40
41
42
43############################################################
44# Program Controls
45############################################################
46$|=1;
47&unsub_handler;
48
49
50############################################################
51# Subroutines
52############################################################
53sub unsub_handler{
54 #One-click unsubscribe from email footer. Resolves the token to a user,
55 #either unsubs a single category (?cat=lifecycle) or all (?unsub_all=1).
56 #Always responds with a public confirmation page even on bad token (so we
57 #don't leak whether the token was real).
58
59 my $tok = $form->{t} || ''; $tok =~ s/[^a-zA-Z0-9]//g;
60 my $cat = $form->{cat} || ''; $cat =~ s/[^a-z]//g;
61 my $all = ($form->{unsub_all} || '') eq '1' ? 1 : 0;
62
63 my $dbh = $db->db_connect;
64
65 #Resolve token -> user
66 my $user_id = 0;
67 my $email = '';
68 if(length($tok) >= 12){
69 my $sql_r = qq~SELECT t.user_id, u.email FROM `${database_name}`.email_unsubscribe_tokens t JOIN `${database_name}`.users u ON u.id = t.user_id WHERE t.token='$tok' LIMIT 1~;
70 my $r = $db->db_readwrite($dbh, $sql_r, $0, __LINE__);
71 if($r && $r->{user_id}){
72 $user_id = $r->{user_id} + 0;
73 $email = $r->{email} || '';
74 }
75 }
76
77 #Apply the unsubscribe(s)
78 my $changed = 0;
79 if($user_id){
80 $db->db_readwrite($dbh, qq~UPDATE `${database_name}`.email_unsubscribe_tokens SET last_used_at=NOW() WHERE token='$tok'~, $0, __LINE__);
81
82 my @cats_to_off;
83 if($all){
84 @cats_to_off = qw(lifecycle product marketing);
85 }elsif($cat =~ /^(lifecycle|product|marketing)$/){
86 @cats_to_off = ($cat);
87 }
88 foreach my $c(@cats_to_off){
89 my $sql_u = qq~INSERT INTO `${database_name}`.user_email_preferences (user_id, category, is_subscribed) VALUES ('$user_id', '$c', 0) ON DUPLICATE KEY UPDATE is_subscribed=0~;
90 $db->db_readwrite($dbh, $sql_u, $0, __LINE__);
91 $changed++;
92 }
93 }
94
95 $db->db_disconnect($dbh);
96
97 #Render the confirmation page
98 print qq~Content-Type: text/html; charset=utf-8\r\nCache-Control: no-store\r\n\r\n~;
99
100 my $email_h = $email;
101 $email_h =~ s/&/&amp;/g; $email_h =~ s/</&lt;/g; $email_h =~ s/>/&gt;/g;
102
103 my $msg;
104 if(!$user_id){
105 $msg = qq~<h1 style="font-size:24px;color:#fff;margin:0 0 14px">Unsubscribe link expired</h1>
106<p style="color:#cbd5e1;font-size:15px;line-height:1.6">That link is no longer valid. If you're signed in, you can manage your email preferences directly:</p>
107<p style="margin-top:18px"><a href="$url->{email_preferences}" style="display:inline-block;background:#5aa9ff;color:#fff;padding:10px 18px;border-radius:6px;text-decoration:none;font-weight:600">Manage preferences</a></p>~;
108 }elsif($all){
109 $msg = qq~<h1 style="font-size:24px;color:#fff;margin:0 0 14px">You're unsubscribed</h1>
110<p style="color:#cbd5e1;font-size:15px;line-height:1.6">We won't send <strong>$email_h</strong> any more lifecycle, product, or marketing emails.</p>
111<p style="color:#94a3b8;font-size:13px;line-height:1.6;margin-top:16px">You'll still get transactional emails (password resets, billing receipts, team invites you accept) because those are essential to using the account.</p>
112<p style="margin-top:18px"><a href="$url->{email_preferences}" style="color:#5aa9ff">Change preferences instead</a></p>~;
113 }elsif($changed){
114 $msg = qq~<h1 style="font-size:24px;color:#fff;margin:0 0 14px">Unsubscribed from $cat</h1>
115<p style="color:#cbd5e1;font-size:15px;line-height:1.6">We won't send <strong>$email_h</strong> any more <strong>$cat</strong> emails.</p>
116<p style="margin-top:18px"><a href="$url->{email_preferences}" style="color:#5aa9ff">Manage all preferences</a></p>~;
117 }else{
118 $msg = qq~<h1 style="font-size:24px;color:#fff;margin:0 0 14px">Manage email preferences</h1>
119<p style="color:#cbd5e1;font-size:15px;line-height:1.6">No category specified. Use the link below to pick which emails you'd like.</p>
120<p style="margin-top:18px"><a href="$url->{email_preferences}" style="display:inline-block;background:#5aa9ff;color:#fff;padding:10px 18px;border-radius:6px;text-decoration:none;font-weight:600">Manage preferences</a></p>~;
121 }
122
123 print qq~<!doctype html><html><head><meta charset="utf-8"><title>Unsubscribe &middot; PTMatrix</title>
124<style>
125body{background:#0b0d10;color:#cbd5e1;font-family:system-ui,-apple-system,sans-serif;margin:0;padding:80px 24px;display:flex;justify-content:center}
126.card{max-width:520px;width:100%;background:rgba(20,20,30,.6);border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:36px 32px}
127.brand{display:flex;align-items:center;gap:10px;margin-bottom:24px}
128.brand-logo{width:32px;height:32px;border-radius:8px;background:#2c0508;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;border:1.5px solid #fff;font-size:13px}
129</style></head><body><div class="card">
130<div class="brand"><div class="brand-logo">PT</div><div style="font-weight:700;color:#fff">PTMatrix</div></div>
131$msg
132</div></body></html>~;
133}
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help