broadfield-dev commited on
Commit
423febb
Β·
verified Β·
1 Parent(s): a87a13d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +150 -65
index.html CHANGED
@@ -1,82 +1,167 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
- <meta charset="UTF-8">
5
- <title>Plugin API Client Example</title>
6
- <style>
7
- body { font-family: sans-serif; max-width: 700px; margin: 2rem auto; }
8
- .container { display: flex; flex-direction: column; gap: 1rem; border: 1px solid #ccc; padding: 1.5rem; border-radius: 8px; }
9
- button { font-size: 1rem; padding: 0.5rem 1rem; cursor: pointer; }
10
- #result { background: #f0f0f0; padding: 1rem; border-radius: 5px; white-space: pre-wrap; font-family: monospace; }
11
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  </head>
13
  <body>
14
- <h1>KeyLock Plugin Client</h1>
15
- <p>This page demonstrates how to send an encrypted image to the decoder plugin API.</p>
16
-
17
- <div class="container">
18
- <div>
19
- <label for="api-url"><b>API Endpoint URL:</b></label>
20
- <input type="text" id="api-url" value="http://'0.0.0.0':7860/api/decode" style="width: 100%;">
21
- </div>
22
- <div>
23
- <label for="image-upload"><b>Upload KeyLock Image:</b></label>
24
- <input type="file" id="image-upload" accept="image/png">
25
- </div>
26
- <button id="submit-button">Decode Image</button>
27
- <div>
28
- <h3>Result:</h3>
29
- <div id="result">...</div>
30
- </div>
31
- </div>
32
 
33
- <script>
34
- const apiUrlInput = document.getElementById('api-url');
35
- const imageInput = document.getElementById('image-upload');
36
- const submitButton = document.getElementById('submit-button');
37
- const resultDiv = document.getElementById('result');
 
 
 
 
38
 
39
- submitButton.addEventListener('click', async () => {
40
- const file = imageInput.files[0];
41
- const apiUrl = apiUrlInput.value;
 
42
 
43
- if (!file) {
44
- resultDiv.textContent = 'Please select an image file first.';
45
- return;
46
- }
47
- if (!apiUrl) {
48
- resultDiv.textContent = 'Please provide the API endpoint URL.';
49
- return;
50
- }
51
 
52
- resultDiv.textContent = 'Uploading and decoding...';
53
- submitButton.disabled = true;
 
54
 
55
- const formData = new FormData();
56
- formData.append('authImage', file);
 
 
 
57
 
58
- try {
59
- const response = await fetch(apiUrl, {
60
- method: 'POST',
61
- body: formData,
62
- });
63
 
64
- const result = await response.json();
 
 
65
 
66
- if (!response.ok) {
67
- throw new Error(result.error || 'An unknown error occurred.');
68
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
- resultDiv.style.color = 'green';
71
- resultDiv.textContent = JSON.stringify(result.data, null, 2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
- } catch (error) {
74
- resultDiv.style.color = 'red';
75
- resultDiv.textContent = `Error: ${error.message}`;
76
- } finally {
77
- submitButton.disabled = false;
78
- }
79
- });
80
- </script>
81
  </body>
82
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>KeyLock Client-Side Decoder Demo</title>
7
+ <style>
8
+ :root {
9
+ --primary-color: #007bff;
10
+ --primary-hover: #0056b3;
11
+ --border-color: #ddd;
12
+ --background-color: #fafafa;
13
+ --text-color: #333;
14
+ --error-color: #dc3545;
15
+ --success-color: #28a745;
16
+ }
17
+ body {
18
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
19
+ line-height: 1.6;
20
+ max-width: 800px;
21
+ margin: 20px auto;
22
+ padding: 0 15px;
23
+ color: var(--text-color);
24
+ }
25
+ main { display: flex; flex-direction: column; gap: 25px; }
26
+ h1 { color: #111; text-align: center; }
27
+ .step { border: 1px solid var(--border-color); padding: 20px; border-radius: 8px; background: var(--background-color); }
28
+ label { font-weight: bold; display: block; margin-bottom: 8px; font-size: 1.1rem; }
29
+ input[type="file"] { display: block; }
30
+ textarea { width: 100%; box-sizing: border-box; padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-family: monospace; font-size: 14px; min-height: 160px; }
31
+ button {
32
+ background-color: var(--primary-color);
33
+ color: white;
34
+ padding: 12px 20px;
35
+ border: none;
36
+ border-radius: 5px;
37
+ font-size: 1.1rem;
38
+ font-weight: bold;
39
+ cursor: pointer;
40
+ transition: background-color 0.2s, transform 0.1s;
41
+ width: 100%;
42
+ }
43
+ button:disabled { background-color: #aaa; cursor: not-allowed; }
44
+ button:hover:not(:disabled) { background-color: var(--primary-hover); }
45
+ button:active:not(:disabled) { transform: translateY(1px); }
46
+ #image-preview {
47
+ max-width: 100%;
48
+ height: auto;
49
+ max-height: 250px;
50
+ margin-top: 15px;
51
+ border: 2px dashed var(--border-color);
52
+ display: none;
53
+ object-fit: contain;
54
+ background: #f0f0f0;
55
+ }
56
+ #result-output {
57
+ margin-top: 10px;
58
+ background: #e9ecef;
59
+ padding: 15px;
60
+ border-radius: 5px;
61
+ white-space: pre-wrap;
62
+ word-wrap: break-word;
63
+ font-family: monospace;
64
+ min-height: 50px;
65
+ border: 1px solid var(--border-color);
66
+ }
67
+ .result-error { color: var(--error-color); border-left: 5px solid var(--error-color); }
68
+ .result-success { color: var(--success-color); border-left: 5px solid var(--success-color); }
69
+ </style>
70
  </head>
71
  <body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
+ <h1>πŸ” KeyLock Client-Side Decoder</h1>
74
+ <p style="text-align:center;">This demo shows how an application can decode a KeyLock image entirely in the user's browser, using their private key. No data is sent to a server.</p>
75
+
76
+ <main>
77
+ <section class="step">
78
+ <label for="stego-image-input">1. Upload your KeyLock Auth Image</label>
79
+ <input type="file" id="stego-image-input" accept="image/png">
80
+ <img id="image-preview" alt="Uploaded image preview for decoding">
81
+ </section>
82
 
83
+ <section class="step">
84
+ <label for="private-key-input">2. Provide your Private Key</label>
85
+ <textarea id="private-key-input" placeholder="Paste your -----BEGIN PRIVATE KEY-----... here. The key never leaves your browser."></textarea>
86
+ </section>
87
 
88
+ <section class="step">
89
+ <label>3. Decode the Image</label>
90
+ <button id="decode-button" disabled>Decode Credentials</button>
91
+ <h3>Result:</h3>
92
+ <div id="result-output">Awaiting input...</div>
93
+ </section>
94
+ </main>
 
95
 
96
+ <script type="module">
97
+ // Import the main function from the decoder module
98
+ import { decodeAuthFromImage } from './keylock-decoder.js';
99
 
100
+ const imageInput = document.getElementById('stego-image-input');
101
+ const imagePreview = document.getElementById('image-preview');
102
+ const keyInput = document.getElementById('private-key-input');
103
+ const decodeButton = document.getElementById('decode-button');
104
+ const resultOutput = document.getElementById('result-output');
105
 
106
+ let isImageLoaded = false;
 
 
 
 
107
 
108
+ function checkInputs() {
109
+ decodeButton.disabled = !isImageLoaded || keyInput.value.trim() === '';
110
+ }
111
 
112
+ imageInput.addEventListener('change', (event) => {
113
+ const file = event.target.files[0];
114
+ if (file) {
115
+ const reader = new FileReader();
116
+ reader.onload = (e) => {
117
+ imagePreview.src = e.target.result;
118
+ imagePreview.style.display = 'block';
119
+ // The 'load' event ensures the image is fully rendered on the page
120
+ imagePreview.onload = () => {
121
+ isImageLoaded = true;
122
+ checkInputs();
123
+ };
124
+ imagePreview.onerror = () => {
125
+ isImageLoaded = false;
126
+ checkInputs();
127
+ alert("Error loading image file.");
128
+ }
129
+ };
130
+ reader.readAsDataURL(file);
131
+ } else {
132
+ isImageLoaded = false;
133
+ imagePreview.style.display = 'none';
134
+ checkInputs();
135
+ }
136
+ });
137
 
138
+ keyInput.addEventListener('input', checkInputs);
139
+
140
+ decodeButton.addEventListener('click', async () => {
141
+ decodeButton.disabled = true;
142
+ decodeButton.textContent = 'Processing...';
143
+ resultOutput.textContent = 'Decoding... please wait.';
144
+ resultOutput.className = ''; // Reset result styles
145
+
146
+ try {
147
+ const credentials = await decodeAuthFromImage(imagePreview, keyInput.value);
148
+
149
+ resultOutput.classList.add('result-success');
150
+ resultOutput.textContent = `βœ… Success!\n\n${JSON.stringify(credentials, null, 2)}`;
151
+
152
+ // In a real app, you would now use the 'credentials' object
153
+ console.log("Decoded Credentials:", credentials);
154
+
155
+ } catch (error) {
156
+ console.error("Decoding failed:", error);
157
+ resultOutput.classList.add('result-error');
158
+ resultOutput.textContent = `❌ Error: ${error.message}`;
159
+ } finally {
160
+ decodeButton.textContent = 'Decode Credentials';
161
+ checkInputs(); // Re-evaluate if the button should be enabled
162
+ }
163
+ });
164
+ </script>
165
 
 
 
 
 
 
 
 
 
166
  </body>
167
  </html>