Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for hideinput.cs

(view source code of hideinput.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text.RegularExpressions;
  4. using System.Windows.Forms;
  5.  
  6.  
  7. namespace RobvanderWoude
  8. {
  9. 	class HideInput
  10. 	{
  11. 		static string progver = "1.03";
  12.  
  13. 		static bool oddrow = false;
  14. 		public static ConsoleColor bold = ConsoleColor.White;
  15.  
  16.  
  17. 		static int Main( string[] args )
  18. 		{
  19. 			bool clearscreen = false;
  20. 			bool filter = false;
  21. 			FilterAction filteraction = FilterAction.Remove;
  22. 			string mask = null;
  23. 			int rc = 0;
  24.  
  25.  
  26. 			#region Command Line Parsing
  27.  
  28. 			if ( args.Length > 0 )
  29. 			{
  30. 				foreach ( string arg in args )
  31. 				{
  32. 					if ( arg.Length > 1 && arg[0] == '/' )
  33. 					{
  34. 						switch ( arg[1].ToString( ).ToUpper( ) )
  35. 						{
  36. 							case "?":
  37. 								return ShowHelp( );
  38. 							case "C":
  39. 								if ( clearscreen )
  40. 								{
  41. 									return ShowHelp( "Duplicate command line switch /C" );
  42. 								}
  43. 								clearscreen = true; // No longer necessary, provided for backwards compatibility only
  44. 								break;
  45. 							case "F":
  46. 								if ( filter )
  47. 								{
  48. 									return ShowHelp( "Duplicate command line switch /F" );
  49. 								}
  50. 								if ( arg.Length > 3 && arg[2] == ':' )
  51. 								{
  52. 									filter = true;
  53. 									string action = arg.Substring( 3 );
  54. 									switch ( action.ToUpper( ) )
  55. 									{
  56. 										case "A":
  57. 										case "ABORT":
  58. 											filteraction = FilterAction.Abort;
  59. 											break;
  60. 										case "D":
  61. 										case "DETECT":
  62. 										case "DETECTONLY":
  63. 											filteraction = FilterAction.DetectOnly;
  64. 											break;
  65. 										case "E":
  66. 										case "END":
  67. 										case "ENDOFINPUT":
  68. 											filteraction = FilterAction.EndOfInput;
  69. 											break;
  70. 										case "R":
  71. 										case "REMOVE":
  72. 											filteraction = FilterAction.Remove;
  73. 											break;
  74. 										case "W":
  75. 										case "WHITESPACE":
  76. 											filteraction = FilterAction.WhiteSpace;
  77. 											break;
  78. 										default:
  79. 											return ShowHelp( "Invalid filter argument \"{0}\"", arg );
  80. 									}
  81. 								}
  82. 								else
  83. 								{
  84. 									return ShowHelp( "Invalid filter argument \"{0}\"", arg );
  85. 								}
  86. 								break;
  87. 							case "M":
  88. 								if ( !String.IsNullOrEmpty( mask ) )
  89. 								{
  90. 									return ShowHelp( "Duplicate command line switch /M" );
  91. 								}
  92. 								if ( arg.Length == 2 )
  93. 								{
  94. 									return HelpForMask( );
  95. 								}
  96. 								if ( arg.Length > 3 && arg[2] == ':' )
  97. 								{
  98. 									mask = arg.Substring( 3 );
  99. 								}
  100. 								else
  101. 								{
  102. 									return ShowHelp( "Invalid mask specification \"{0}\"", arg );
  103. 								}
  104. 								break;
  105. 							default:
  106. 								return ShowHelp( "Invalid command line argument \"{0}\"", arg );
  107. 						}
  108. 					}
  109. 					else
  110. 					{
  111. 						return ShowHelp( "Invalid command line argument \"{0}\"", arg );
  112. 					}
  113. 				}
  114. 			}
  115.  
  116. 			#endregion Command Line Parsing
  117.  
  118.  
  119. 			#region Read Input
  120.  
  121. 			// Read 1 line of input from the console
  122. 			string input = String.Empty;
  123. 			char key = (char) 27;
  124. 			while ( key != (char) 13 )
  125. 			{
  126. 				ConsoleKeyInfo keyinfo = Console.ReadKey( true );
  127. 				key = keyinfo.KeyChar;
  128. 				if ( key != (char) 13 )
  129. 				{
  130. 					input += keyinfo.KeyChar.ToString( );
  131. 				}
  132. 			}
  133.  
  134. 			#endregion Read Input
  135.  
  136.  
  137. 			#region Clear Screen
  138.  
  139. 			// Though no longer necessary for safety, this feature is provided for backwards compatibility
  140. 			if ( clearscreen )
  141. 			{
  142. 				Console.Clear( );
  143. 			}
  144.  
  145. 			#endregion Clear Screen
  146.  
  147.  
  148. 			#region Apply Mask to Input
  149.  
  150. 			if ( !String.IsNullOrEmpty( mask ) )
  151. 			{
  152. 				using ( MaskedTextBox maskedtextbox = new MaskedTextBox( mask ) )
  153. 				{
  154. 					maskedtextbox.Text = String.Empty;
  155. 					maskedtextbox.AppendText( input );
  156. 					input = maskedtextbox.Text;
  157. 				}
  158. 			}
  159.  
  160. 			#endregion Apply Mask to Input
  161.  
  162.  
  163. 			#region Apply Filter to Output
  164.  
  165. 			if ( filter )
  166. 			{
  167. 				string specialchars= @"(\^|&|\||<|>|\(|\)|\""|'|\\|%|!)";
  168. 				Regex regex = new Regex( specialchars );
  169. 				if ( regex.IsMatch( input ) )
  170. 				{
  171. 					rc = 3;
  172. 					switch ( filteraction )
  173. 					{
  174. 						case FilterAction.Abort:
  175. 							input = String.Empty;
  176. 							break;
  177. 						case FilterAction.DetectOnly:
  178. 							break;
  179. 						case FilterAction.EndOfInput:
  180. 							int pos = input.IndexOfAny( "^&|<>()\"'\\%!".ToCharArray( ) );
  181. 							if ( pos != -1 )
  182. 							{
  183. 								input = input.Substring( 0, pos );
  184. 							}
  185. 							break;
  186. 						case FilterAction.Remove:
  187. 							input = regex.Replace( input, "" );
  188. 							break;
  189. 						case FilterAction.WhiteSpace:
  190. 							input = regex.Replace( input, " " );
  191. 							break;
  192. 					}
  193. 				}
  194. 			}
  195.  
  196. 			#endregion Apply Filter to Output
  197.  
  198.  
  199. 			// Display the input - which should be redirected for this program to be of any use
  200. 			Console.WriteLine( input );
  201.  
  202. 			// Returncode 0 for success, 2 if the input was empty or whitespace only, 3 if "forbidden" characters were detected
  203. 			if ( rc != 3 && string.IsNullOrWhiteSpace( input ) )
  204. 			{
  205. 				rc = 2;
  206. 			}
  207. 			return rc;
  208. 		}
  209.  
  210.  
  211. 		public static int HelpForMask()
  212. 		{
  213. 			int col1perc = 13;
  214. 			Console.Error.Write( "Help for command line switch " );
  215. 			Console.ForegroundColor = bold;
  216. 			Console.Error.WriteLine( "/M:mask" );
  217. 			Console.ResetColor( );
  218. 			Console.Error.WriteLine( );
  219. 			Console.Error.Write( "The " );
  220. 			Console.ForegroundColor = bold;
  221. 			Console.Error.Write( "mask" );
  222. 			Console.ResetColor( );
  223. 			Console.Error.WriteLine( " \"language\" is based on the Masked Edit control in Visual Basic 6.0:" );
  224. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  225. 			string url1 = "http://msdn.microsoft.com/en-us/library/";
  226. 			string url2 = "system.windows.forms.maskedtextbox.mask.aspx#remarksToggle";
  227. 			if ( url1.Length + url2.Length > Console.WindowWidth )
  228. 			{
  229. 				Console.Error.WriteLine( url1 );
  230. 				Console.Error.WriteLine( url2 );
  231. 			}
  232. 			else
  233. 			{
  234. 				Console.Error.WriteLine( url1 + url2 );
  235. 			}
  236. 			Console.ResetColor( );
  237. 			Console.Error.WriteLine( );
  238. 			WriteTableRow( "Masking element", "Description", col1perc, true, true );
  239. 			WriteTableRow( "0", "Digit, required. This element will accept any single digit between 0 and 9.", col1perc );
  240. 			WriteTableRow( "9", "Digit or space, optional.", col1perc );
  241. 			WriteTableRow( "#", "Digit or space, optional. If this position is blank in the mask, it will be rendered as a space in the Text property. Plus (+) and minus (-) signs are allowed.", col1perc );
  242. 			WriteTableRow( "L", "Letter, required. Restricts input to the ASCII letters a-z and A-Z. This mask element is equivalent to [a-zA-Z] in regular expressions.", col1perc );
  243. 			WriteTableRow( "?", "Letter, optional. Restricts input to the ASCII letters a-z and A-Z. This mask element is equivalent to [a-zA-Z]? in regular expressions.", col1perc );
  244. 			WriteTableRow( "&", "Character, required. Any non-control character. If ASCII only is set (/A), this element behaves like the \"A\" element.", col1perc );
  245. 			WriteTableRow( "C", "Character, optional. Any non-control character. If ASCII only is set (/A), this element behaves like the \"a\" element.", col1perc );
  246. 			WriteTableRow( "A", "Alphanumeric, required. If ASCII only is set (/A), the only characters it will accept are the ASCII letters a-z and A-Z and numbers. This mask element behaves like the \"&\" element.", col1perc );
  247. 			WriteTableRow( "a", "Alphanumeric, optional. If ASCII only is set (/A), the only characters it will accept are the ASCII letters a-z and A-Z and numbers. This mask element behaves like the \"C\" element.", col1perc );
  248. 			WriteTableRow( ".", "Decimal placeholder.", col1perc );
  249. 			WriteTableRow( ",", "Thousands placeholder.", col1perc );
  250. 			WriteTableRow( ":", "Time separator.", col1perc );
  251. 			WriteTableRow( "/", "Date separator.", col1perc );
  252. 			WriteTableRow( "$", "Currency symbol.", col1perc );
  253. 			WriteTableRow( "<", "Shift down. Converts all characters that follow to lowercase.", col1perc );
  254. 			WriteTableRow( ">", "Shift up. Converts all characters that follow to uppercase.", col1perc );
  255. 			WriteTableRow( "|", "Disable a previous shift up or shift down.", col1perc );
  256. 			WriteTableRow( @"\", "Escape. Escapes a mask character, turning it into a literal. \"\\\\\" is the escape sequence for a backslash.", col1perc );
  257. 			WriteTableRow( "All other characters", "Literals. All non-mask elements will appear as themselves within MaskedTextBox. Literals always occupy a static position in the mask at run time, and cannot be moved or deleted by the user.", col1perc );
  258.  
  259. 			return 1;
  260. 		}
  261.  
  262.  
  263. 		public static int ShowHelp( params string[] errmsg )
  264. 		{
  265. 			#region Help Text
  266.  
  267. 			/*
  268. 			HideInput,  Version 1.03
  269. 			Batch utility to read 1 line of input while hiding what's being typed
  270.  
  271. 			Usage:   FOR /F "tokens=*" %%A IN ('HIDEINPUT  [ options ]') DO SET passwd=%%A
  272.  
  273. 			   or:   HIDEINPUT  [ options ] > file
  274.  
  275. 			Options: /C        Clear screen afterwards (no longer required to remove input
  276. 			                   from keyboard buffer; provided for backwards compatibility)
  277. 			         /F:action Filter special characters ^ & | < > ( ) " ' % ! and \
  278. 			                   action can be A = Abort (input is discarded), D = DetectOnly
  279. 			                   (input is left unchanged), E = EndOfInput (input is chopped
  280. 			                   at first "forbidden" character), R = Remove (remove
  281. 			                   "forbidden" characters) or W = WhiteSpace (replace
  282. 			                   "forbidden" characters with spaces)
  283. 			         /M:mask   specifies an optional mask that will be applied to the input
  284.  
  285. 			Notes:   HIDEINPUT /M without a mask will show help for the "mask language".
  286. 			         Return code ("errorlevel") is 0 if valid input is received, 1 in case
  287. 			         of (command line) errors, 2 if input is empty or whitespace only, 3 if
  288. 			         "forbidden" characters were detected by the filter.
  289.  
  290. 			Written by Rob van der Woude
  291. 			http://www.robvanderwoude.com
  292. 			*/
  293.  
  294. 			#endregion Help Text
  295.  
  296.  
  297. 			#region Error Message
  298.  
  299. 			if ( errmsg.Length > 0 )
  300. 			{
  301. 				List<string> errargs = new List<string>( errmsg );
  302. 				errargs.RemoveAt( 0 );
  303. 				Console.Error.WriteLine( );
  304. 				Console.ForegroundColor = ConsoleColor.Red;
  305. 				Console.Error.Write( "ERROR:\t" );
  306. 				Console.ForegroundColor = ConsoleColor.White;
  307. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  308. 				Console.ResetColor( );
  309. 			}
  310.  
  311. 			#endregion Error Message
  312.  
  313.  
  314. 			#region Display Help Text
  315.  
  316. 			Console.Error.WriteLine( );
  317.  
  318. 			Console.Error.WriteLine( "HideInput,  Version {0}", progver );
  319.  
  320. 			Console.Error.WriteLine( "Batch utility to read 1 line of input while hiding what's being typed" );
  321.  
  322. 			Console.Error.WriteLine( );
  323.  
  324. 			Console.Error.Write( "Usage:   FOR /F \"tokens=*\" %%A IN ('" );
  325. 			Console.ForegroundColor = ConsoleColor.White;
  326. 			Console.Error.Write( "HIDEINPUT  [ options ]" );
  327. 			Console.ResetColor( );
  328. 			Console.Error.WriteLine( "') DO SET passwd=%%A" );
  329.  
  330. 			Console.Error.WriteLine( );
  331.  
  332. 			Console.Error.Write( "   or:   " );
  333. 			Console.ForegroundColor = ConsoleColor.White;
  334. 			Console.Error.WriteLine( "HIDEINPUT  [ options ] > file" );
  335. 			Console.ResetColor( );
  336.  
  337. 			Console.Error.WriteLine( );
  338.  
  339. 			Console.Error.Write( "Options: " );
  340. 			Console.ForegroundColor = ConsoleColor.White;
  341. 			Console.Error.Write( "/C        C" );
  342. 			Console.ResetColor( );
  343. 			Console.Error.WriteLine( "lear screen afterwards (no longer required to remove input" );
  344.  
  345. 			Console.Error.WriteLine( "                   from keyboard buffer; provided for backwards compatibility)" );
  346.  
  347. 			Console.ForegroundColor = ConsoleColor.White;
  348. 			Console.Error.Write( "         /F:action F" );
  349. 			Console.ResetColor( );
  350. 			Console.Error.WriteLine( "ilter special characters ^ & | < > ( ) \" ' % ! and \\" );
  351.  
  352. 			Console.ForegroundColor = ConsoleColor.White;
  353. 			Console.Error.Write( "                   action" );
  354. 			Console.ResetColor( );
  355. 			Console.Error.Write( " can be " );
  356. 			Console.ForegroundColor = ConsoleColor.White;
  357. 			Console.Error.Write( "A" );
  358. 			Console.ResetColor( );
  359. 			Console.Error.Write( " = Abort (input is discarded), " );
  360. 			Console.ForegroundColor = ConsoleColor.White;
  361. 			Console.Error.Write( "D" );
  362. 			Console.ResetColor( );
  363. 			Console.Error.WriteLine( " = DetectOnly" );
  364.  
  365. 			Console.Error.Write( "                   (input is left unchanged), " );
  366. 			Console.ForegroundColor = ConsoleColor.White;
  367. 			Console.Error.Write( "E" );
  368. 			Console.ResetColor( );
  369. 			Console.Error.WriteLine( " = EndOfInput (input is chopped" );
  370.  
  371. 			Console.Error.Write( "                   at first \"forbidden\" character), " );
  372. 			Console.ForegroundColor = ConsoleColor.White;
  373. 			Console.Error.Write( "R" );
  374. 			Console.ResetColor( );
  375. 			Console.Error.WriteLine( " = Remove (remove" );
  376.  
  377. 			Console.Error.Write( "                   \"forbidden\" characters) or " );
  378. 			Console.ForegroundColor = ConsoleColor.White;
  379. 			Console.Error.Write( "W" );
  380. 			Console.ResetColor( );
  381. 			Console.Error.WriteLine( " = WhiteSpace (replace" );
  382.  
  383. 			Console.Error.WriteLine( "                   \"forbidden\" characters with spaces)" );
  384.  
  385. 			Console.ForegroundColor = ConsoleColor.White;
  386. 			Console.Error.Write( "         /M:mask" );
  387. 			Console.ResetColor( );
  388. 			Console.Error.Write( "   specifies an optional " );
  389. 			Console.ForegroundColor = ConsoleColor.White;
  390. 			Console.Error.Write( "mask" );
  391. 			Console.ResetColor( );
  392. 			Console.Error.WriteLine( " that will be applied to the input" );
  393.  
  394. 			Console.Error.WriteLine( );
  395.  
  396. 			Console.Error.Write( "Notes:   " );
  397. 			Console.ForegroundColor = ConsoleColor.White;
  398. 			Console.Error.Write( "HIDEINPUT /M" );
  399. 			Console.ResetColor( );
  400. 			Console.Error.WriteLine( " without a mask will show help for the \"mask language\"." );
  401.  
  402. 			Console.Error.WriteLine( "         Return code (\"errorlevel\") is 0 if valid input is received, 1 in case" );
  403.  
  404. 			Console.Error.WriteLine( "         of (command line) errors, 2 if input is empty or whitespace only, 3 if" );
  405.  
  406. 			Console.Error.WriteLine( "         \"forbidden\" characters were detected by the filter." );
  407.  
  408. 			Console.Error.WriteLine( );
  409.  
  410. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  411.  
  412. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  413.  
  414. 			#endregion Display Help Text
  415.  
  416.  
  417. 			return 1;
  418. 		}
  419.  
  420.  
  421. 		static void WriteTableRow( string col1text, string col2text, int col1percentage, bool col1bold = true, bool col2bold = false )
  422. 		{
  423. 			// Wrap text to fit in 2 columns
  424. 			oddrow = !oddrow;
  425. 			int windowwidth = Console.WindowWidth;
  426. 			int col1width = Convert.ToInt32( windowwidth * col1percentage / 100 );
  427. 			int col2width = windowwidth - col1width - 5; // Column separator = 4, subtract 1 extra to prevent automatic line wrap
  428. 			List<string> col1lines = new List<string>( );
  429. 			List<string> col2lines = new List<string>( );
  430. 			// Column 1
  431. 			if ( col1text.Length > col1width )
  432. 			{
  433. 				Regex regex = new Regex( @".{1," + col1width + @"}(?=\s|$)" );
  434. 				if ( regex.IsMatch( col1text ) )
  435. 				{
  436. 					MatchCollection matches = regex.Matches( col1text );
  437. 					foreach ( Match match in matches )
  438. 					{
  439. 						col1lines.Add( match.ToString( ).Trim( ) );
  440. 					}
  441. 				}
  442. 				else
  443. 				{
  444. 					while ( col1text.Length > 0 )
  445. 					{
  446. 						col1lines.Add( col1text.Trim( ).Substring( 0, Math.Min( col1width, col1text.Length ) ) );
  447. 						col1text = col1text.Substring( Math.Min( col1width, col1text.Length ) ).Trim( );
  448. 					}
  449. 				}
  450. 			}
  451. 			else
  452. 			{
  453. 				col1lines.Add( col1text.Trim( ) );
  454. 			}
  455. 			// Column 2
  456. 			if ( col2text.Length > col2width )
  457. 			{
  458. 				Regex regex = new Regex( @".{1," + col2width + @"}(?=\s|$)" );
  459. 				if ( regex.IsMatch( col2text ) )
  460. 				{
  461. 					MatchCollection matches = regex.Matches( col2text );
  462. 					foreach ( Match match in matches )
  463. 					{
  464. 						col2lines.Add( match.ToString( ).Trim( ) );
  465. 					}
  466. 				}
  467. 				else
  468. 				{
  469. 					while ( col2text.Length > 0 )
  470. 					{
  471. 						col2lines.Add( col2text.Trim( ).Substring( 0, Math.Min( col2width, col2text.Length ) ) );
  472. 						col2text = col2text.Substring( Math.Min( col2width, col2text.Length ) ).Trim( );
  473. 					}
  474. 				}
  475. 			}
  476. 			else
  477. 			{
  478. 				col2lines.Add( col2text.Trim( ) );
  479. 			}
  480. 			for ( int i = 0; i < Math.Max( col1lines.Count, col2lines.Count ); i++ )
  481. 			{
  482. 				if ( oddrow )
  483. 				{
  484. 					Console.BackgroundColor = ConsoleColor.DarkGray;
  485. 				}
  486. 				if ( col1bold || oddrow )
  487. 				{
  488. 					Console.ForegroundColor = bold;
  489. 				}
  490. 				Console.Write( "{0,-" + col1width + "}    ", ( i < col1lines.Count ? col1lines[i] : String.Empty ) );
  491. 				Console.ResetColor( );
  492. 				if ( oddrow )
  493. 				{
  494. 					Console.BackgroundColor = ConsoleColor.DarkGray;
  495. 				}
  496. 				if ( col2bold || oddrow )
  497. 				{
  498. 					Console.ForegroundColor = bold;
  499. 				}
  500. 				Console.WriteLine( "{0,-" + col2width + "}", ( i < col2lines.Count ? col2lines[i] : String.Empty ) );
  501. 				Console.ResetColor( );
  502. 			}
  503. 		}
  504. 	}
  505.  
  506.  
  507. 	public enum FilterAction
  508. 	{
  509. 		Abort,
  510. 		DetectOnly,
  511. 		EndOfInput,
  512. 		Remove,
  513. 		WhiteSpace
  514. 	}
  515. }
  516.  

page last modified: 2024-04-16; loaded in 0.0215 seconds