4sp-dv 1.1.12 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/logged-in/securly-tester.html +248 -0
- package/package.json +1 -1
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" class="dark">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>4SP - URL Tester</title>
|
|
7
|
+
|
|
8
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
|
+
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap" rel="stylesheet">
|
|
11
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
|
|
12
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
13
|
+
|
|
14
|
+
<style>
|
|
15
|
+
body {
|
|
16
|
+
font-family: 'Geist', sans-serif;
|
|
17
|
+
background-color: #040404;
|
|
18
|
+
color: #c0c0c0;
|
|
19
|
+
font-weight: 300;
|
|
20
|
+
height: 100vh;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* --- UI COMPONENTS --- */
|
|
27
|
+
.btn-toolbar-style {
|
|
28
|
+
background: #000000;
|
|
29
|
+
border: 1px solid #333;
|
|
30
|
+
border-radius: 0.75rem;
|
|
31
|
+
color: #d1d5db;
|
|
32
|
+
padding: 0.75rem 1.25rem;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
transition: all 0.2s;
|
|
36
|
+
display: inline-flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
gap: 0.5rem;
|
|
40
|
+
}
|
|
41
|
+
.btn-toolbar-style:hover {
|
|
42
|
+
border-color: #fff;
|
|
43
|
+
color: #ffffff;
|
|
44
|
+
transform: translateY(-1px);
|
|
45
|
+
}
|
|
46
|
+
.btn-toolbar-style:active {
|
|
47
|
+
transform: scale(0.98);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.btn-primary-override {
|
|
51
|
+
background-color: rgba(79, 70, 229, 0.1);
|
|
52
|
+
border: 1px solid #4f46e5;
|
|
53
|
+
color: #4f46e5;
|
|
54
|
+
}
|
|
55
|
+
.btn-primary-override:hover {
|
|
56
|
+
background-color: rgba(79, 70, 229, 0.2);
|
|
57
|
+
border-color: #6366f1;
|
|
58
|
+
color: #6366f1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.input-text-style {
|
|
62
|
+
width: 100%;
|
|
63
|
+
padding: 0.75rem;
|
|
64
|
+
border: 1px solid #252525;
|
|
65
|
+
background-color: #111111;
|
|
66
|
+
border-radius: 0.75rem;
|
|
67
|
+
color: #c0c0c0;
|
|
68
|
+
transition: all 0.2s;
|
|
69
|
+
outline: none;
|
|
70
|
+
}
|
|
71
|
+
.input-text-style:focus {
|
|
72
|
+
border-color: #505050;
|
|
73
|
+
box-shadow: 0 0 0 2px rgba(80, 80, 80, 0.5);
|
|
74
|
+
transform: scale(1.01);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.card-box {
|
|
78
|
+
background-color: #0d0d0d;
|
|
79
|
+
border: 1px solid #1a1a1a;
|
|
80
|
+
border-radius: 1rem;
|
|
81
|
+
padding: 2rem;
|
|
82
|
+
width: 100%;
|
|
83
|
+
max-width: 600px;
|
|
84
|
+
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Status Colors */
|
|
88
|
+
.status-box {
|
|
89
|
+
padding: 1rem;
|
|
90
|
+
border-radius: 0.75rem;
|
|
91
|
+
text-align: center;
|
|
92
|
+
font-weight: 500;
|
|
93
|
+
margin-top: 1.5rem;
|
|
94
|
+
border: 1px solid transparent;
|
|
95
|
+
transition: all 0.3s;
|
|
96
|
+
}
|
|
97
|
+
.status-blocked {
|
|
98
|
+
background-color: rgba(185, 28, 28, 0.1);
|
|
99
|
+
border-color: #7f1d1d;
|
|
100
|
+
color: #fca5a5;
|
|
101
|
+
}
|
|
102
|
+
.status-allowed {
|
|
103
|
+
background-color: rgba(21, 128, 61, 0.1);
|
|
104
|
+
border-color: #14532d;
|
|
105
|
+
color: #86efac;
|
|
106
|
+
}
|
|
107
|
+
.status-info {
|
|
108
|
+
background-color: #1a1a1a;
|
|
109
|
+
border-color: #333;
|
|
110
|
+
color: #9ca3af;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.loading-spinner {
|
|
114
|
+
animation: spin 1s linear infinite;
|
|
115
|
+
}
|
|
116
|
+
@keyframes spin { 100% { transform: rotate(360deg); } }
|
|
117
|
+
</style>
|
|
118
|
+
</head>
|
|
119
|
+
<body>
|
|
120
|
+
|
|
121
|
+
<div class="flex-grow flex flex-col items-center justify-center p-4">
|
|
122
|
+
|
|
123
|
+
<div class="mb-8 text-center">
|
|
124
|
+
<h1 class="text-3xl text-white font-light tracking-tight mb-2">Securly URL Tester</h1>
|
|
125
|
+
<p class="text-gray-500 text-sm">Check if a website is blocked on the US-EAST server.</p>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<div class="card-box">
|
|
129
|
+
|
|
130
|
+
<div class="mb-6">
|
|
131
|
+
<label class="block text-gray-500 text-xs uppercase tracking-wider mb-2 font-semibold">Student Email</label>
|
|
132
|
+
<input type="email" id="email-input" class="input-text-style font-mono text-sm !bg-[#1a1a1a] !border-[#333]" placeholder="student@school.edu">
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
<div class="mb-6">
|
|
136
|
+
<label class="block text-gray-500 text-xs uppercase tracking-wider mb-2 font-semibold">Target URL</label>
|
|
137
|
+
<input type="text" id="url-input" class="input-text-style" placeholder="example.com" value="zapatopi.net/treeoctopus/">
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<button id="check-btn" class="btn-toolbar-style btn-primary-override w-full justify-center">
|
|
141
|
+
<i class="fa-solid fa-search"></i> Check Status
|
|
142
|
+
</button>
|
|
143
|
+
|
|
144
|
+
<div id="result-box" class="status-box status-info">
|
|
145
|
+
Ready to check
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<p class="mt-4 text-xs text-center text-gray-600">
|
|
149
|
+
<i class="fa-solid fa-shield-halved mr-1"></i> Uses CORS Proxy to bypass local restrictions.
|
|
150
|
+
</p>
|
|
151
|
+
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<script>
|
|
156
|
+
const emailInput = document.getElementById('email-input');
|
|
157
|
+
const urlInput = document.getElementById('url-input');
|
|
158
|
+
const checkBtn = document.getElementById('check-btn');
|
|
159
|
+
const resultBox = document.getElementById('result-box');
|
|
160
|
+
|
|
161
|
+
const SECURLY_SERVER = 'https://useast-www.securly.com';
|
|
162
|
+
const CORS_PROXY = 'https://corsproxy.io/?';
|
|
163
|
+
|
|
164
|
+
// --- AUTH DETECTION ---
|
|
165
|
+
function detectUser() {
|
|
166
|
+
let userEmail = '';
|
|
167
|
+
// 1. Try injected window.currentUser (from 4simpleproblems_v5.html)
|
|
168
|
+
if (window.currentUser && window.currentUser.email) {
|
|
169
|
+
userEmail = window.currentUser.email;
|
|
170
|
+
}
|
|
171
|
+
// 2. Try parent scope if accessible
|
|
172
|
+
else if (window.parent && window.parent.currentUser && window.parent.currentUser.email) {
|
|
173
|
+
userEmail = window.parent.currentUser.email;
|
|
174
|
+
}
|
|
175
|
+
// 3. Fallback/Default
|
|
176
|
+
else {
|
|
177
|
+
userEmail = 'client@4sp'; // Default for testing/unauthed
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
emailInput.value = userEmail;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// --- CHECK LOGIC ---
|
|
184
|
+
async function checkStatus() {
|
|
185
|
+
const rawUrl = urlInput.value.trim();
|
|
186
|
+
const userEmail = emailInput.value.trim();
|
|
187
|
+
if (!rawUrl || !userEmail) return;
|
|
188
|
+
|
|
189
|
+
// Normalize URL
|
|
190
|
+
let targetUrl = rawUrl;
|
|
191
|
+
if (!targetUrl.startsWith('http')) {
|
|
192
|
+
targetUrl = 'https://' + targetUrl;
|
|
193
|
+
}
|
|
194
|
+
urlInput.value = targetUrl; // Update input
|
|
195
|
+
|
|
196
|
+
// UI Loading
|
|
197
|
+
checkBtn.disabled = true;
|
|
198
|
+
checkBtn.innerHTML = '<i class="fa-solid fa-spinner loading-spinner"></i> Checking...';
|
|
199
|
+
resultBox.className = 'status-box status-info';
|
|
200
|
+
resultBox.innerHTML = 'Connecting to Securly...';
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
// Construct Securly Broker URL
|
|
204
|
+
let hostname;
|
|
205
|
+
try { hostname = new URL(targetUrl).hostname; } catch(e) { hostname = targetUrl; }
|
|
206
|
+
|
|
207
|
+
const securlyUrl = `${SECURLY_SERVER}/crextn/broker?useremail=${encodeURIComponent(userEmail)}&reason=crextn&host=${encodeURIComponent(hostname)}&url=${btoa(targetUrl)}&msg=&ver=2.97.13&cu=${encodeURIComponent(SECURLY_SERVER + "/crextn")}&uf=1&cf=1`;
|
|
208
|
+
|
|
209
|
+
const proxyUrl = CORS_PROXY + encodeURIComponent(securlyUrl);
|
|
210
|
+
|
|
211
|
+
const response = await fetch(proxyUrl);
|
|
212
|
+
const text = await response.text();
|
|
213
|
+
|
|
214
|
+
if (text.includes('DENY')) {
|
|
215
|
+
resultBox.className = 'status-box status-blocked';
|
|
216
|
+
resultBox.innerHTML = '<i class="fa-solid fa-ban mr-2"></i> BLOCKED (DENY)';
|
|
217
|
+
} else if (text.includes('ALLOW')) {
|
|
218
|
+
resultBox.className = 'status-box status-allowed';
|
|
219
|
+
resultBox.innerHTML = '<i class="fa-solid fa-check-circle mr-2"></i> ALLOWED';
|
|
220
|
+
} else {
|
|
221
|
+
resultBox.className = 'status-box status-info';
|
|
222
|
+
resultBox.innerHTML = '<i class="fa-solid fa-question-circle mr-2"></i> STATUS UNKNOWN';
|
|
223
|
+
console.log('Securly Response:', text);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
} catch (err) {
|
|
227
|
+
console.error(err);
|
|
228
|
+
resultBox.className = 'status-box status-blocked';
|
|
229
|
+
resultBox.innerHTML = '<i class="fa-solid fa-exclamation-triangle mr-2"></i> NETWORK ERROR';
|
|
230
|
+
} finally {
|
|
231
|
+
checkBtn.disabled = false;
|
|
232
|
+
checkBtn.innerHTML = '<i class="fa-solid fa-search"></i> Check Status';
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// --- INIT ---
|
|
237
|
+
window.addEventListener('load', () => {
|
|
238
|
+
detectUser();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
checkBtn.addEventListener('click', checkStatus);
|
|
242
|
+
urlInput.addEventListener('keypress', (e) => {
|
|
243
|
+
if (e.key === 'Enter') checkStatus();
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
</script>
|
|
247
|
+
</body>
|
|
248
|
+
</html>
|