1 /*
2  * steghide 0.5.1 - a steganography program
3  * Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  */
20 
21 #include <cstring>
22 #include <iostream>
23 #include <string>
24 
25 #include "MCryptPP.h"
26 #include "Terminal.h"
27 #include "common.h"
28 #include "error.h"
29 #include "msg.h"
30 
31 // the global Arguments object
32 Arguments Args ;
33 
Arguments(int argc,char * argv[])34 Arguments::Arguments (int argc, char* argv[])
35 {
36 	bool delete_next = false ;
37 	for (int i = 1 ; i < argc ; ++i) {
38 		TheArguments.push_back (std::string(argv[i])) ;
39 
40 		if (delete_next) {
41 			// overwrite passphrase in argv in order to avoid that it can be read with the ps command
42 			unsigned int len = strlen(argv[i]) ;
43 			for (unsigned int j = 0 ; j < len ; j++) {
44 				argv[i][j] = ' ' ;
45 			}
46 			delete_next = false ;
47 		}
48 
49 		if (std::string(argv[i]) == "-p" || std::string(argv[i]) == "--passphrase") {
50 			delete_next = true ;
51 		}
52 	}
53 }
54 
parse()55 void Arguments::parse ()
56 {
57 	// if there are no arguments -> show help
58 	if (TheArguments.empty()) {
59 		Command.setValue (SHOWHELP) ;
60 		return ;
61 	}
62 
63 	ArgIt curarg = TheArguments.begin() ;
64 
65 	parse_Command (curarg) ;
66 
67 	// parse rest of arguments
68 	while (curarg != TheArguments.end()) {
69 		if (parse_EmbFn(curarg)) continue ;
70 		if (parse_ExtFn(curarg)) continue ;
71 		if (parse_CvrFn(curarg)) continue ;
72 		if (parse_StgFn(curarg)) continue ;
73 		if (parse_Passphrase(curarg)) continue ;
74 		if (parse_Checksum(curarg)) continue ;
75 		if (parse_Compression(curarg)) continue ;
76 		if (parse_EmbedEmbFn(curarg)) continue ;
77 		if (parse_Encryption(curarg)) continue ;
78 		if (parse_Radius(curarg)) continue ;
79 		if (parse_Goal(curarg)) continue ;
80 		if (parse_Force(curarg)) continue ;
81 		if (parse_Verbosity(curarg)) continue ;
82 		if (parse_Debug(curarg)) continue ; // TODO - rename Debug -> Undocumented
83 
84 		throw ArgError (_("unknown argument \"%s\"."), curarg->c_str()) ;
85 	}
86 
87 	// (command-specific) argument post-processing
88 	if (Command.getValue() == EMBED) {
89 		if ((CvrFn.getValue() == "") && (EmbFn.getValue() == "")) {
90 			throw ArgError (_("standard input cannot be used for cover data AND data to be embedded.")) ;
91 		}
92 		if (!StgFn.is_set() && CvrFn.is_set()) {
93 			StgFn.setValue (CvrFn.getValue()) ;
94 			Force.setValue (true) ;
95 		}
96 	}
97 
98 	if (Command.getValue() == EMBED || Command.getValue() == EXTRACT) {
99 		if (!Passphrase.is_set()) {
100 			// prompt for passphrase
101 			if (Command.getValue() == EMBED) {
102 				if ((CvrFn.getValue() == "") || (EmbFn.getValue() == "")) {
103 					throw ArgError (_("if standard input is used, the passphrase must be specified on the command line.")) ;
104 				}
105 				Passphrase.setValue (getPassphrase (true)) ;
106 			}
107 			else if (Command.getValue() == EXTRACT) {
108 				if (StgFn.getValue() == "") {
109 					throw ArgError (_("if standard input is used, the passphrase must be specified on the command line.")) ;
110 				}
111 				Passphrase.setValue (getPassphrase()) ;
112 			}
113 		}
114 	}
115 }
116 
parse_Command(ArgIt & curarg)117 void Arguments::parse_Command (ArgIt& curarg)
118 {
119 	CommandString = *curarg ;
120 
121 	if (*curarg == "embed" || *curarg == "--embed") {
122 		Command.setValue (EMBED) ;
123 		setDefaults () ;
124 		++curarg ;
125 	}
126 	else if (*curarg == "extract" || *curarg == "--extract") {
127 		Command.setValue (EXTRACT) ;
128 		setDefaults () ;
129 		++curarg ;
130 	}
131 	else if (*curarg == "info" || *curarg == "--info") {
132 		Command.setValue (INFO) ;
133 		setDefaults() ;
134 
135 		++curarg ;
136 
137 		if (curarg == TheArguments.end()) {
138 			throw ArgError (_("you have to suppy a filename to the \"%s\" command."), CommandString.c_str()) ;
139 		}
140 		else {
141 			parse_Passphrase (curarg) ; // try: maybe -p is first argument
142 
143 			if (*curarg == "-") {
144 				CvrFn.setValue ("") ;
145 			}
146 			else {
147 				CvrFn.setValue (*curarg) ;
148 			}
149 			++curarg ;
150 
151 			if (curarg != TheArguments.end()) {
152 				parse_Passphrase (curarg) ;
153 			}
154 		}
155 	}
156 	else if (*curarg == "encinfo" || *curarg == "--encinfo") {
157 		Command.setValue (ENCINFO) ;
158 		if (TheArguments.size() > 1) {
159 			throw ArgError (_("you cannot use arguments with the \"%s\" command."), CommandString.c_str()) ;
160 		}
161 		++curarg ;
162 	}
163 	else if (*curarg == "version" || *curarg == "--version") {
164 		Command.setValue (SHOWVERSION) ;
165 		if (TheArguments.size() > 1) {
166 			throw ArgError (_("you cannot use arguments with the \"%s\" command."), CommandString.c_str()) ;
167 		}
168 		++curarg ;
169 	}
170 	else if (*curarg == "license" || *curarg == "--license") {
171 		Command.setValue (SHOWLICENSE) ;
172 		if (TheArguments.size() > 1) {
173 			throw ArgError (_("you cannot use arguments with the \"%s\" command."), CommandString.c_str()) ;
174 		}
175 		++curarg ;
176 	}
177 	else if (*curarg == "help" || *curarg == "--help") {
178 		Command.setValue (SHOWHELP) ;
179 		if (TheArguments.size() > 1) {
180 			throw ArgError (_("you cannot use arguments with the \"%s\" command."), CommandString.c_str()) ;
181 		}
182 		++curarg ;
183 	}
184 #ifdef DEBUG
185 	else if (*curarg == "printfreqs" || *curarg == "--printfreqs") {
186 		Command.setValue (PRINTFREQS) ;
187 		std::list<std::string> flist ;
188 		while ((++curarg) != TheArguments.end()) {
189 			flist.push_back (*curarg) ;
190 		}
191 		FileList.setValue (flist) ;
192 	}
193 #endif
194 	else {
195 		throw ArgError (_("unknown command \"%s\"."), CommandString.c_str()) ;
196 	}
197 }
198 
parse_EmbFn(ArgIt & curarg)199 bool Arguments::parse_EmbFn (ArgIt& curarg)
200 {
201 	bool found = false ;
202 
203 	if (*curarg == "-ef" || *curarg == "--embedfile") {
204 		if (Command.getValue() != EMBED) {
205 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
206 		}
207 
208 		if (EmbFn.is_set()) {
209 			throw ArgError (_("the \"%s\" argument can be used only once."), (curarg - 1)->c_str()) ;
210 		}
211 
212 		if (++curarg == TheArguments.end()) {
213 			throw ArgError (_("the \"%s\" argument must be followed by the embed file name."), (curarg - 1)->c_str()) ;
214 		}
215 
216 		if (*curarg == "-") {
217 			EmbFn.setValue ("") ;
218 		}
219 		else {
220 			EmbFn.setValue (*curarg) ;
221 		}
222 
223 		found = true ;
224 		curarg++ ;
225 	}
226 
227 	return found ;
228 }
229 
parse_ExtFn(ArgIt & curarg)230 bool Arguments::parse_ExtFn (ArgIt& curarg)
231 {
232 	bool found = false ;
233 
234 	if (*curarg == "-xf" || *curarg == "--extractfile") {
235 		if (Command.getValue() != EXTRACT) {
236 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "extract") ;
237 		}
238 
239 		if (ExtFn.is_set()) {
240 			throw ArgError (_("the \"%s\" argument can be used only once."), (curarg - 1)->c_str()) ;
241 		}
242 
243 		if (++curarg == TheArguments.end()) {
244 			throw ArgError (_("the \"%s\" argument must be followed by the extract file name."), (curarg - 1)->c_str()) ;
245 		}
246 
247 		if (*curarg == "-") {
248 			ExtFn.setValue ("") ;
249 		}
250 		else {
251 			ExtFn.setValue (*curarg) ;
252 		}
253 
254 		found = true ;
255 		curarg++ ;
256 	}
257 
258 	return found ;
259 }
260 
parse_CvrFn(ArgIt & curarg)261 bool Arguments::parse_CvrFn (ArgIt& curarg)
262 {
263 	bool found = false ;
264 
265 	if (*curarg == "-cf" || *curarg == "--coverfile") {
266 		if (Command.getValue() != EMBED) {
267 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
268 		}
269 
270 		if (CvrFn.is_set()) {
271 			throw ArgError (_("the cover file name argument can be used only once.")) ;
272 		}
273 
274 		if (++curarg == TheArguments.end()) {
275 			throw ArgError (_("the \"%s\" argument must be followed by the cover file name."), (curarg - 1)->c_str()) ;
276 		}
277 
278 		if (*curarg == "-") {
279 			CvrFn.setValue ("") ;
280 		}
281 		else {
282 			CvrFn.setValue (*curarg) ;
283 		}
284 
285 		found = true ;
286 		curarg++ ;
287 	}
288 
289 	return found ;
290 }
291 
parse_StgFn(ArgIt & curarg)292 bool Arguments::parse_StgFn (ArgIt& curarg)
293 {
294 	bool found = false ;
295 
296 	if (*curarg == "-sf" || *curarg == "--stegofile") {
297 		if (Command.getValue() != EMBED && Command.getValue() != EXTRACT) {
298 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" and \"%s\" commands."), curarg->c_str(), "embed", "extract") ;
299 		}
300 
301 		if (StgFn.is_set()) {
302 			throw ArgError (_("the \"%s\" argument can be used only once."), (curarg - 1)->c_str()) ;
303 		}
304 
305 		if (++curarg == TheArguments.end()) {
306 			throw ArgError (_("the \"%s\" argument must be followed by the stego file name."), (curarg - 1)->c_str()) ;
307 		}
308 
309 		if (*curarg == "-") {
310 			StgFn.setValue ("") ;
311 		}
312 		else {
313 			StgFn.setValue (*curarg) ;
314 		}
315 
316 		found = true ;
317 		curarg++ ;
318 	}
319 
320 	return found ;
321 }
322 
parse_Passphrase(ArgIt & curarg)323 bool Arguments::parse_Passphrase (ArgIt& curarg)
324 {
325 	bool found = false ;
326 
327 	if (*curarg == "-p" || *curarg == "--passphrase") {
328 		if (Passphrase.is_set()) {
329 			throw ArgError (_("the passphrase argument can be used only once.")) ;
330 		}
331 
332 		if (++curarg == TheArguments.end()) {
333 			throw ArgError (_("the \"%s\" argument must be followed by the passphrase."), (curarg - 1)->c_str());
334 		}
335 
336 		Passphrase.setValue (*curarg) ;
337 
338 		found = true ;
339 		curarg++ ;
340 	}
341 
342 	return found ;
343 }
344 
parse_Checksum(ArgIt & curarg)345 bool Arguments::parse_Checksum (ArgIt& curarg)
346 {
347 	bool found = false ;
348 
349 	if (*curarg == "-K" || *curarg == "--nochecksum") {
350 		if (Command.getValue() != EMBED) {
351 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
352 		}
353 
354 		if (Checksum.is_set()) {
355 			throw ArgError (_("the checksum argument can be used only once.")) ;
356 		}
357 
358 		Checksum.setValue (false) ;
359 
360 		found = true ;
361 		curarg++ ;
362 	}
363 
364 	return found ;
365 }
366 
parse_Compression(ArgIt & curarg)367 bool Arguments::parse_Compression (ArgIt& curarg)
368 {
369 	bool found = false ;
370 
371 	if (*curarg == "-z" || *curarg == "--compress") {
372 		if (Command.getValue() != EMBED) {
373 			throw ArgError (_("the argument \"%s\" can only be used with the \"embed\" command."), curarg->c_str()) ;
374 		}
375 
376 		if (Compression.is_set()) {
377 			throw ArgError (_("the compression argument can be used only once.")) ;
378 		}
379 
380 		if (++curarg == TheArguments.end()) {
381 			throw ArgError (_("the \"%s\" argument must be followed by the compression level."), (curarg - 1)->c_str()) ;
382 		}
383 
384 		int tmp = 0 ;
385 		sscanf (curarg->c_str(), "%d", &tmp) ;
386 		if (tmp < 1 || tmp > 9) {
387 			throw ArgError (_("\"%s\" is not a valid compression level."), curarg->c_str()) ;
388 		}
389 		Compression.setValue (tmp) ;
390 
391 		found = true ;
392 		curarg++ ;
393 	}
394 	else if (*curarg == "-Z" || *curarg == "--dontcompress") {
395 		if (Command.getValue() != EMBED) {
396 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
397 		}
398 
399 		if (Compression.is_set()) {
400 			throw ArgError (_("the compression argument can be used only once.")) ;
401 		}
402 
403 		Compression.setValue (NoCompression) ;
404 
405 		found = true ;
406 		curarg++ ;
407 	}
408 
409 	return found ;
410 }
411 
parse_EmbedEmbFn(ArgIt & curarg)412 bool Arguments::parse_EmbedEmbFn (ArgIt& curarg)
413 {
414 	bool found = false ;
415 
416 	if (*curarg == "-N" || *curarg == "--dontembedname") {
417 		if (Command.getValue() != EMBED) {
418 			throw ArgError (_("the argument \"%s\" can only be used with the \"embed\" command."), curarg->c_str()) ;
419 		}
420 
421 		if (EmbedEmbFn.is_set()) {
422 			throw ArgError (_("the file name embedding argument can be used only once.")) ;
423 		}
424 
425 		EmbedEmbFn.setValue (false) ;
426 
427 		found = true ;
428 		curarg++ ;
429 	}
430 
431 	return found ;
432 }
433 
parse_Encryption(ArgIt & curarg)434 bool Arguments::parse_Encryption (ArgIt& curarg)
435 {
436 	bool found = false ;
437 
438 	if (*curarg == "-e" || *curarg == "--encryption") {
439 		if (Command.getValue() != EMBED) {
440 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
441 		}
442 
443 		if (EncAlgo.is_set() || EncMode.is_set()) {
444 			throw ArgError (_("the encryption argument can be used only once.")) ;
445 		}
446 
447 		if (++curarg == TheArguments.end()) {
448 			throw ArgError (_("the \"%s\" argument must be followed by encryption parameters."), (curarg - 1)->c_str()) ;
449 		}
450 
451 		std::string s1, s2 ;
452 		if ((*curarg)[0] == '-') {
453 			throw ArgError (_("the \"%s\" argument must be followed by encryption parameters."), (curarg - 1)->c_str()) ;
454 		}
455 		else {
456 			s1 = *curarg ;
457 			if (curarg + 1 == TheArguments.end()) {
458 				s2 = "" ;
459 			}
460 			else {
461 				if ((*(curarg + 1))[0] == '-') {
462 					s2 = "" ;
463 				}
464 				else {
465 					++curarg ; // set to second encryption specifier
466 					s2 = *curarg ;
467 				}
468 			}
469 		}
470 
471 		if (s1 == "none" && s2 == "") {
472 			EncAlgo.setValue (s1) ;
473 		}
474 #ifdef USE_LIBMCRYPT
475 		else {
476 			bool s1_isalgo = false, s1_ismode = false ;
477 			bool s2_isalgo = false, s2_ismode = false ;
478 
479 			if (s1 != "") {
480 				s1_isalgo = EncryptionAlgorithm::isValidStringRep (s1) ;
481 				s1_ismode = EncryptionMode::isValidStringRep (s1) ;
482 
483 				myassert (!(s1_isalgo && s1_ismode)) ;
484 				if (!(s1_isalgo || s1_ismode)) {
485 					throw SteghideError (_("\"%s\" is neither an algorithm nor a mode supported by libmcrypt."), s1.c_str()) ;
486 				}
487 			}
488 			if (s2 != "") {
489 				s2_isalgo = EncryptionAlgorithm::isValidStringRep (s2) ;
490 				s2_ismode = EncryptionMode::isValidStringRep (s2) ;
491 
492 				myassert (!(s2_isalgo && s2_ismode)) ;
493 				if (!(s2_isalgo || s2_ismode)) {
494 					throw SteghideError (_("\"%s\" is neither an algorithm nor a mode supported by libmcrypt."), s2.c_str()) ;
495 				}
496 			}
497 
498 			if (s1_isalgo && s2_isalgo) {
499 				throw SteghideError (_("\"%s\" and \"%s\" are both libmcrypt algorithms. please specify only one."), s1.c_str(), s2.c_str()) ;
500 			}
501 			if (s1_ismode && s2_ismode) {
502 				throw SteghideError (_("\"%s\" and \"%s\" are both libmcrypt modes. please specify only one."), s1.c_str(), s2.c_str()) ;
503 			}
504 
505 			if (s1_isalgo) {
506 				EncAlgo.setValue (s1) ;
507 			}
508 			if (s1_ismode) {
509 				EncMode.setValue (s1) ;
510 			}
511 			if (s2_isalgo) {
512 				EncAlgo.setValue (s2) ;
513 			}
514 			if (s2_ismode) {
515 				EncMode.setValue (s2) ;
516 			}
517 
518 			if (!MCryptPP::AlgoSupportsMode (EncAlgo.getValue(), EncMode.getValue())) {
519 				throw SteghideError (_("the encryption algorithm \"%s\" can not be used with the mode \"%s\"."),
520 					EncAlgo.getValue().getStringRep().c_str(), EncMode.getValue().getStringRep().c_str()) ;
521 			}
522 		}
523 #else
524 		else {
525 			throw SteghideError (_("steghide has been compiled without support for encryption.")) ;
526 		}
527 #endif // def USE_LIBMCRYPT
528 
529 		found = true ;
530 		curarg++ ;
531 	}
532 
533 	return found ;
534 }
535 
parse_Radius(ArgIt & curarg)536 bool Arguments::parse_Radius (ArgIt& curarg)
537 {
538 	bool found = false ;
539 
540 	if (*curarg == "-r" || *curarg == "--radius") {
541 		if (Command.getValue() != EMBED) {
542 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
543 		}
544 
545 		if (Radius.is_set()) {
546 			throw ArgError (_("the radius argument can be used only once.")) ;
547 		}
548 
549 		if (++curarg == TheArguments.end()) {
550 			throw ArgError (_("the \"%s\" argument must be followed by the neighbourhood radius."), (curarg - 1)->c_str()) ;
551 		}
552 
553 		unsigned long tmp = 0 ;
554 		sscanf (curarg->c_str(), "%lu", &tmp) ;
555 		Radius.setValue (tmp) ;
556 
557 		found = true ;
558 		curarg++ ;
559 	}
560 
561 	return found ;
562 }
563 
parse_Goal(ArgIt & curarg)564 bool Arguments::parse_Goal (ArgIt& curarg)
565 {
566 	bool found = false ;
567 
568 	if (*curarg == "-g" || *curarg == "--goal") {
569 		if (Command.getValue() != EMBED) {
570 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
571 		}
572 
573 		if (Goal.is_set()) {
574 			throw ArgError (_("the goal argument can be used only once.")) ;
575 		}
576 
577 		if (++curarg == TheArguments.end()) {
578 			throw ArgError (_("the \"%s\" argument must be followed by a number between 0 and 100."), (curarg - 1)->c_str()) ;
579 		}
580 
581 		float tmp = 0 ;
582 		sscanf (curarg->c_str(), "%f", &tmp) ;
583 		if (tmp < 0 || tmp > 100) {
584 			throw ArgError (_("the \"%s\" argument must be followed by a number between 0 and 100."), (curarg - 1)->c_str()) ;
585 		}
586 		Goal.setValue (tmp) ;
587 
588 		found = true ;
589 		curarg++ ;
590 	}
591 
592 	return found ;
593 }
594 
parse_Force(ArgIt & curarg)595 bool Arguments::parse_Force (ArgIt& curarg)
596 {
597 	bool found = false ;
598 
599 	if (*curarg == "-f" || *curarg == "--force") {
600 		if (Command.getValue() != EMBED && Command.getValue() != EXTRACT) {
601 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" and \"%s\" commands."), curarg->c_str(), "embed", "extract") ;
602 		}
603 
604 		if (Force.is_set()) {
605 			throw ArgError (_("the force argument can be used only once.")) ;
606 		}
607 
608 		Force.setValue (true);
609 
610 		found = true ;
611 		curarg++ ;
612 	}
613 
614 	return found ;
615 }
616 
parse_Verbosity(ArgIt & curarg)617 bool Arguments::parse_Verbosity (ArgIt& curarg)
618 {
619 	bool found = false ;
620 
621 	if (*curarg == "-q" || *curarg == "--quiet") {
622 		found = true ;
623 
624 		if (Command.getValue() != EMBED && Command.getValue() != EXTRACT) {
625 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" and \"%s\" commands."), curarg->c_str(), "embed", "extract") ;
626 		}
627 
628 		if (Verbosity.is_set()) {
629 			throw ArgError (_("the \"%s\" argument cannot be used here because the verbosity has already been set."), curarg->c_str()) ;
630 		}
631 
632 		Verbosity.setValue (QUIET) ;
633 		curarg++ ;
634 	}
635 	else if (*curarg == "-v" || *curarg == "--verbose") {
636 		found = true ;
637 
638 		if (Command.getValue() != EMBED && Command.getValue() != EXTRACT) {
639 			throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" and \"%s\" commands."), curarg->c_str(), "embed", "extract") ;
640 		}
641 
642 		if (Verbosity.is_set()) {
643 			throw ArgError (_("the \"%s\" argument cannot be used here because the verbosity has already been set."), curarg->c_str()) ;
644 		}
645 
646 		Verbosity.setValue (VERBOSE) ;
647 		curarg++ ;
648 	}
649 
650 	return found ;
651 }
652 
parse_Debug(ArgIt & curarg)653 bool Arguments::parse_Debug (ArgIt& curarg)
654 {
655 	bool found = false ;
656 
657 	if (*curarg == "--printgraph") {
658 		if (DebugCommand.is_set()) {
659 			throw SteghideError (_("you cannot use more than one debug command at a time.")) ;
660 		}
661 
662 		DebugCommand.setValue (PRINTGRAPH) ;
663 
664 		found = true ;
665 		curarg++ ;
666 	}
667 	else if (*curarg == "--printgmlgraph") {
668 		if (DebugCommand.is_set()) {
669 			throw SteghideError (_("you cannot use more than one debug command at a time.")) ;
670 		}
671 
672 		DebugCommand.setValue (PRINTGMLGRAPH) ;
673 
674 		found = true ;
675 		curarg++ ;
676 	}
677 	else if (*curarg == "--printgmlvertex") {
678 		if (DebugCommand.is_set()) {
679 			throw SteghideError (_("you cannot use more than one debug command at a time.")) ;
680 		}
681 
682 		DebugCommand.setValue (PRINTGMLVERTEX) ;
683 		curarg++ ;
684 
685 		int tmp = 0 ;
686 		sscanf (curarg->c_str(), "%d", &tmp) ;
687 		GmlGraphRecDepth.setValue (tmp) ;
688 		curarg++ ;
689 		sscanf (curarg->c_str(), "%d", &tmp) ;
690 		GmlStartVertex.setValue (tmp) ;
691 
692 		found = true ;
693 		curarg++ ;
694 	}
695 	else if (*curarg == "--printstats") {
696 		if (DebugCommand.is_set()) {
697 			throw SteghideError (_("you cannot use more than one debug command at a time.")) ;
698 		}
699 
700 		if (Verbosity.is_set()) {
701 			throw ArgError (_("the \"%s\" argument cannot be used here because the verbosity has already been set."), curarg->c_str()) ;
702 		}
703 
704 		Verbosity.setValue (STATS) ;
705 
706 		found = true ;
707 		++curarg ;
708 	}
709 	else if (*curarg == "--debuglevel") {
710 		if (DebugLevel.is_set()) {
711 			throw ArgError (_("the debug level argument can be used only once.")) ;
712 		}
713 
714 		if (++curarg == TheArguments.end()) {
715 			throw ArgError (_("the \"%s\" argument must be followed by the debug level."), (curarg - 1)->c_str()) ;
716 		}
717 
718 		unsigned int tmp = 0 ;
719 		sscanf (curarg->c_str(), "%u", &tmp) ;
720 		DebugLevel.setValue (tmp) ;
721 
722 		found = true ;
723 		++curarg ;
724 	}
725 	else if (*curarg == "--check") {
726 		// TODO usual error checking (omitted due to message freeze)
727 		Check.setValue (true) ;
728 
729 		found = true ;
730 		++curarg ;
731 	}
732 
733 	return found ;
734 }
735 
getPassphrase(bool doublecheck)736 std::string Arguments::getPassphrase (bool doublecheck)
737 {
738     int c = EOF ;
739 
740 #ifndef HAVE_TERMIOS_H
741 	Warning w (_("unknown terminal. the passphrase you type now will be visible.")) ;
742 	w.printMessage() ;
743 #endif
744 
745 	std::cerr << _("Enter passphrase: ") ;
746 	Terminal term ;
747 	term.EchoOff() ;
748 
749     std::string s1 = "" ;
750     while ((c = std::cin.get()) != '\n') {
751         s1 += c ;
752     }
753 
754 	term.reset() ;
755 	std::cerr << std::endl ;
756 
757 	if (doublecheck) {
758 		std::cerr << _("Re-Enter passphrase: ") ;
759 		term.EchoOff() ;
760 
761 		std::string s2 = "" ;
762 		while ((c = std::cin.get()) != '\n') {
763 			s2 += c ;
764 		}
765 
766 		term.reset() ;
767 		std::cerr << std::endl ;
768 
769 		if (s1 != s2) {
770 			throw SteghideError (_("the passphrases do not match.")) ;
771 		}
772 	}
773 
774 	return s1 ;
775 }
776 
stdin_isused() const777 bool Arguments::stdin_isused () const
778 {
779 	bool retval = false ;
780 	if (Command.getValue() == EMBED && (EmbFn.getValue() == "" || CvrFn.getValue() == "")) {
781 		retval = true ;
782 	}
783 	else if (Command.getValue() == EXTRACT && StgFn.getValue() == "") {
784 		retval = true ;
785 	}
786 	else if (Command.getValue() == INFO && CvrFn.getValue() == "") {
787 		retval = true ;
788 	}
789 	return retval ;
790 }
791 
setDefaults(void)792 void Arguments::setDefaults (void)
793 {
794 	myassert (Command.is_set()) ;
795 
796 	EmbFn.setValue ("", false) ;
797 	CvrFn.setValue ("", false) ;
798 	EncAlgo.setValue (Default_EncAlgo, false) ;
799 	EncMode.setValue (Default_EncMode, false) ;
800 	Checksum.setValue (Default_Checksum, false) ;
801 	Compression.setValue (Default_Compression, false) ;
802 	EmbedEmbFn.setValue (Default_EmbedEmbFn, false) ;
803 	ExtFn.setValue ("", false) ;
804 	Passphrase.setValue ("", false) ;
805 	StgFn.setValue ("", false) ;
806 	Force.setValue (Default_Force, false) ;
807 	Verbosity.setValue (Default_Verbosity, false) ;
808 	Radius.setValue (Default_Radius, false) ;
809 	Goal.setValue (Default_Goal, false) ;
810 	Check.setValue (Default_Check, false) ;
811 	DebugCommand.setValue (Default_DebugCommand, false) ;
812 	DebugLevel.setValue (Default_DebugLevel, false) ;
813 	GmlGraphRecDepth.setValue (Default_GmlGraphRecDepth, false) ;
814 	GmlStartVertex.setValue (Default_GmlStartVertex, false) ;
815 }
816 
817 #ifdef USE_LIBMCRYPT
818 const EncryptionAlgorithm Arguments::Default_EncAlgo = EncryptionAlgorithm (EncryptionAlgorithm::RIJNDAEL128) ;
819 const EncryptionMode Arguments::Default_EncMode = EncryptionMode (EncryptionMode::CBC) ;
820 #else
821 const EncryptionAlgorithm Arguments::Default_EncAlgo = EncryptionAlgorithm (EncryptionAlgorithm::NONE) ;
822 const EncryptionMode Arguments::Default_EncMode = EncryptionMode (EncryptionMode::ECB) ; // is ignored
823 #endif
824