@@ -3,6 +3,10 @@ if (!window.WebAssembly) {
33 alert ( "WebAssembly is not supported in your browser. Please use a modern browser." ) ;
44}
55
6+ const cipherModeInput = document . getElementById ( 'cipherModeInput' ) ;
7+ const steganoModeInput = document . getElementById ( 'steganoModeInput' ) ;
8+ const msgInputContainer = document . getElementById ( 'msgInput-container' ) ;
9+ const msgInput = document . getElementById ( 'msgInput' ) ;
610const secretInput = document . getElementById ( 'secretInput' ) ;
711const fileInput = document . getElementById ( 'fileInput' ) ;
812const limitMaxSideInput = document . getElementById ( 'limitMaxSide' ) ;
@@ -15,16 +19,60 @@ const decodeButton = document.getElementById('decodeButton');
1519const downloadBtn = document . getElementById ( 'downloadBtn' ) ;
1620const errorDiv = document . getElementById ( 'error' ) ;
1721const imTypeSelect = document . getElementById ( 'imTypeSelect' ) ;
22+ const imTypeContainer = document . getElementById ( 'imType-container' ) ;
1823const downloadBtnContainer = document . getElementById ( 'downloadBtn-container' ) ;
1924const outputContainer = document . getElementById ( 'output-container' ) ;
2025const footer = document . getElementById ( 'footer' ) ;
2126
2227const worker = new Worker ( './worker.js' , { type : 'module' } ) ;
2328
24- const urlParams = new URLSearchParams ( window . location . search ) ;
25- const secretFromUrl = urlParams . get ( 'secret' ) || urlParams . get ( 's' ) ;
26- if ( secretFromUrl ) {
27- secretInput . value = decodeURIComponent ( secretFromUrl ) ;
29+ function onModeChange ( mode ) {
30+ if ( mode === 'cipher' ) {
31+ msgInputContainer . style . display = 'none' ;
32+ imTypeSelect . disabled = false ;
33+ imTypeContainer . style . display = 'block' ;
34+ } else if ( mode === 'stegano' ) {
35+ msgInputContainer . style . display = 'flex' ;
36+ imTypeSelect . value = 'png' ;
37+ imTypeSelect . dispatchEvent ( new Event ( 'change' ) ) ;
38+ imTypeSelect . disabled = true ;
39+ imTypeContainer . style . display = 'none' ;
40+ }
41+ }
42+
43+ // handle initial mode setup
44+ {
45+ const urlParams = new URLSearchParams ( window . location . search ) ;
46+ const secretFromUrl = urlParams . get ( 'secret' ) || urlParams . get ( 's' ) ;
47+ if ( secretFromUrl ) {
48+ secretInput . value = decodeURIComponent ( secretFromUrl ) ;
49+ }
50+ const modeFromUrl = urlParams . get ( 'mode' ) || urlParams . get ( 'm' ) ;
51+ switch ( modeFromUrl ) {
52+ case 'stega' :
53+ case 'stegano' :
54+ case 'steganography' :
55+ cipherModeInput . checked = false ;
56+ steganoModeInput . checked = true ;
57+ onModeChange ( 'stegano' ) ;
58+ break ;
59+ case 'cipher' :
60+ case 'cryptography' :
61+ default :
62+ cipherModeInput . checked = true ;
63+ steganoModeInput . checked = false ;
64+ onModeChange ( 'cipher' ) ;
65+ break ;
66+ }
67+ }
68+
69+ function getMode ( ) {
70+ if ( cipherModeInput . checked ) {
71+ return 'cipher' ;
72+ } else if ( steganoModeInput . checked ) {
73+ return 'stegano' ;
74+ }
75+ throw new Error ( "No mode selected" ) ;
2876}
2977
3078async function getInputBlob ( ) {
@@ -100,13 +148,28 @@ async function encode_image() {
100148 hintLabel . textContent = `Encoding...` ;
101149
102150 ensureOutput ( ) ;
103- worker . postMessage ( {
104- type : 'encode' ,
105- buffer : inputBlob ,
106- secret : secretInput . value ,
107- maxSide : limitMaxSideInput . checked ? parseInt ( maxSideInput . value ) : - 1 ,
108- outputAs : imTypeSelect . value
109- } ) ;
151+ switch ( getMode ( ) ) {
152+ case 'cipher' :
153+ worker . postMessage ( {
154+ type : 'encode' ,
155+ buffer : inputBlob ,
156+ secret : secretInput . value ,
157+ maxSide : limitMaxSideInput . checked ? parseInt ( maxSideInput . value ) : - 1 ,
158+ outputAs : imTypeSelect . value
159+ } ) ;
160+ break ;
161+ case 'stegano' :
162+ worker . postMessage ( {
163+ type : 'stega_encode' ,
164+ buffer : inputBlob ,
165+ secret : secretInput . value ,
166+ message : msgInput . value ,
167+ maxSide : limitMaxSideInput . checked ? parseInt ( maxSideInput . value ) : - 1 ,
168+ } ) ;
169+ break ;
170+ default :
171+ throw new Error ( "Unknown mode" ) ;
172+ }
110173}
111174
112175async function decode_image ( ) {
@@ -117,13 +180,27 @@ async function decode_image() {
117180 hintLabel . textContent = `Decoding...` ;
118181
119182 ensureOutput ( ) ;
120- worker . postMessage ( {
121- type : 'decode' ,
122- buffer : inputBlob ,
123- secret : secretInput . value ,
124- maxSide : limitMaxSideInput . checked ? parseInt ( maxSideInput . value ) : - 1 ,
125- outputAs : imTypeSelect . value
126- } ) ;
183+ switch ( getMode ( ) ) {
184+ case 'cipher' :
185+ worker . postMessage ( {
186+ type : 'decode' ,
187+ buffer : inputBlob ,
188+ secret : secretInput . value ,
189+ maxSide : limitMaxSideInput . checked ? parseInt ( maxSideInput . value ) : - 1 ,
190+ outputAs : imTypeSelect . value
191+ } ) ;
192+ break ;
193+ case 'stegano' :
194+ worker . postMessage ( {
195+ type : 'stega_decode' ,
196+ buffer : inputBlob ,
197+ secret : secretInput . value ,
198+ maxSide : limitMaxSideInput . checked ? parseInt ( maxSideInput . value ) : - 1 ,
199+ } ) ;
200+ break ;
201+ default :
202+ throw new Error ( "Unknown mode" ) ;
203+ }
127204}
128205
129206worker . onmessage = async ( event ) => {
@@ -133,18 +210,41 @@ worker.onmessage = async (event) => {
133210 hintLabel . textContent = '' ;
134211 return ;
135212 }
136- await showImage (
137- event . data . type ,
138- event . data . buffer ,
139- event . data . format
140- ) ;
213+ if ( event . data . buffer ) {
214+ await showImage (
215+ event . data . type ,
216+ event . data . buffer ,
217+ event . data . format
218+ ) ;
219+ }
220+ if ( event . data . message ) {
221+ resetOutput ( ) ;
222+ ensureOutput ( ) ;
223+ hintLabel . textContent = '' ;
224+ const messageElem = document . createElement ( 'pre' ) ;
225+ messageElem . textContent = event . data . message ;
226+ outputDiv . appendChild ( messageElem ) ;
227+ messageElem . style . whiteSpace = 'pre-wrap' ;
228+ downloadBtnContainer . style . display = 'none' ;
229+ }
141230} ;
142231
143232// Event listeners for inputs
144233{
145234 encodeButton . addEventListener ( 'click' , encode_image ) ;
146235 decodeButton . addEventListener ( 'click' , decode_image ) ;
147236
237+ steganoModeInput . addEventListener ( 'change' , ( ) => {
238+ if ( steganoModeInput . checked ) {
239+ onModeChange ( 'stegano' ) ;
240+ }
241+ } )
242+ cipherModeInput . addEventListener ( 'change' , ( ) => {
243+ if ( cipherModeInput . checked ) {
244+ onModeChange ( 'cipher' ) ;
245+ }
246+ } )
247+
148248 imTypeSelect . addEventListener ( 'change' , ( ) => {
149249 if ( imTypeSelect . value === 'jpeg' ) {
150250 encodeButton . disabled = true ;
0 commit comments