Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for checkvarsvbs.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7.  
  8.  
  9. namespace RobvanderWoude
  10. {
  11. 	class CheckVarsVBS
  12. 	{
  13. 		static readonly string progver = "1.05";
  14.  
  15.  
  16. 		static List<string> csserrors = new List<string>( );
  17.  
  18.  
  19. 		static int Main( string[] args )
  20. 		{
  21. 			#region Initialize Variables
  22.  
  23. 			int rc = 0;
  24. 			SortedList<string, int> subroutines = new SortedList<string, int>( );
  25. 			SortedList<string, int> variables = new SortedList<string, int>( );
  26. 			bool htawindowevents = false;
  27. 			bool showsubs = true;
  28. 			bool showvars = true;
  29. 			bool unusedonly = false;
  30. 			string scriptcode = String.Empty;
  31. 			string scriptext = String.Empty;
  32. 			string scriptfile = String.Empty;
  33. 			int columnwidth = 12;
  34. 			int unusedsubs = 0;
  35. 			int unusedvars = 0;
  36. 			List<string> ignoredsubs = new List<string>( )
  37. 			{
  38. 				"window_onbeforeunload",
  39. 				"window_onblur",
  40. 				"window_onfocus",
  41. 				"window_onhelp",
  42. 				"window_onload",
  43. 				"window_onresize",
  44. 				"window_onunload"
  45. 			};
  46.  
  47. 			#endregion Initialize Variables
  48.  
  49.  
  50. 			#region Command Line Parsing
  51.  
  52. 			if ( args.Length == 0 )
  53. 			{
  54. 				return ShowHelp( );
  55. 			}
  56.  
  57. 			foreach ( string arg in args )
  58. 			{
  59. 				if ( arg[0] == '/' )
  60. 				{
  61. 					if ( arg.ToUpper( ) == "/?" )
  62. 					{
  63. 						return ShowHelp( );
  64. 					}
  65. 					else if ( arg.ToUpper( ) == "/S" )
  66. 					{
  67. 						if ( !showvars )
  68. 						{
  69. 							return ShowHelp( "Duplicate command line switch /S" );
  70. 						}
  71. 						if ( !showsubs )
  72. 						{
  73. 							return ShowHelp( "Use /S or /V or neither, but not both" );
  74. 						}
  75. 						showvars = false;
  76. 					}
  77. 					else if ( arg.ToUpper( ) == "/U" )
  78. 					{
  79. 						if ( unusedonly )
  80. 						{
  81. 							return ShowHelp( "Duplicate command line switch /U" );
  82. 						}
  83. 						unusedonly = true;
  84. 					}
  85. 					else if ( arg.ToUpper( ) == "/V" )
  86. 					{
  87. 						if ( !showsubs )
  88. 						{
  89. 							return ShowHelp( "Duplicate command line switch /V" );
  90. 						}
  91. 						if ( !showvars )
  92. 						{
  93. 							return ShowHelp( "Use /S or /V or neither, but not both" );
  94. 						}
  95. 						showsubs = false;
  96. 					}
  97. 					else if ( arg.ToUpper( ) == "/W" )
  98. 					{
  99. 						if ( htawindowevents )
  100. 						{
  101. 							return ShowHelp( "Duplicate command line switch /W" );
  102. 						}
  103. 						htawindowevents = true;
  104. 					}
  105. 					else
  106. 					{
  107. 						return ShowHelp( "Invalid command line switch \"{0}\"", arg );
  108. 					}
  109. 				}
  110. 				else
  111. 				{
  112. 					if ( !String.IsNullOrWhiteSpace( scriptfile ) )
  113. 					{
  114. 						return ShowHelp( "Duplicate command line argument for VBScript file" );
  115. 					}
  116. 					if ( !File.Exists( arg ) )
  117. 					{
  118. 						return ShowHelp( "Invalid file name or file not found: \"{0}\"", arg );
  119. 					}
  120. 					scriptext = Path.GetExtension( arg ).ToLower( );
  121. 					if ( scriptext != ".hta" && scriptext != ".vbs" )
  122. 					{
  123. 						return ShowHelp( "Invalid file type \"{0}\"", arg );
  124. 					}
  125. 					scriptfile = Path.GetFullPath( arg );
  126. 				}
  127.  
  128. 			}
  129.  
  130. 			if ( String.IsNullOrWhiteSpace( scriptfile ) )
  131. 			{
  132. 				return ShowHelp( "Please specify a source file" );
  133. 			}
  134.  
  135. 			#endregion Command Line Parsing
  136.  
  137.  
  138. 			#region Read File
  139.  
  140. 			// Read the code from the file
  141. 			scriptcode = File.ReadAllText( scriptfile, Encoding.UTF8 );
  142. 			// Remove comment lines from the code (does NOT strip comments starting halfway on a line)
  143. 			string pattern = @"(^|\n|\r)[ \t]*'[^\n\r]+";
  144. 			Regex regex = new Regex( pattern );
  145. 			scriptcode = regex.Replace( scriptcode, String.Empty );
  146.  
  147. 			#endregion Read File
  148.  
  149.  
  150. 			#region List Subroutines
  151.  
  152. 			// Create a list of subroutines found in the code
  153. 			if ( showsubs )
  154. 			{
  155. 				pattern = @"(?:^|\n|\r)[ \t]*(?:Sub|Function)[ \t]+([A-Z][^\s\(]+)";
  156. 				regex = new Regex( pattern, RegexOptions.IgnoreCase );
  157. 				if ( regex.IsMatch( scriptcode ) )
  158. 				{
  159. 					MatchCollection matches = regex.Matches( scriptcode );
  160. 					if ( matches.Count > 0 )
  161. 					{
  162. 						foreach ( Match match in matches )
  163. 						{
  164. 							bool listed = false;
  165. 							string sub = match.Groups[1].Value;
  166. 							foreach ( string key in subroutines.Keys )
  167. 							{
  168. 								if ( sub.ToLower( ) == key.ToLower( ) )
  169. 								{
  170. 									listed = true;
  171. 								}
  172. 							}
  173. 							if ( !listed )
  174. 							{
  175. 								if ( sub.ToLower( ).StartsWith( "window_on" ) )
  176. 								{
  177. 									subroutines[sub] = 1;
  178. 								}
  179. 								else
  180. 								{
  181. 									subroutines[sub] = 0;
  182. 								}
  183. 								if ( sub.Length > columnwidth )
  184. 								{
  185. 									columnwidth = sub.Length;
  186. 								}
  187. 							}
  188. 						}
  189. 					}
  190. 				}
  191. 			}
  192.  
  193. 			#endregion List Subroutines
  194.  
  195.  
  196. 			#region Check Subroutine Nesting
  197.  
  198. 			if ( showsubs )
  199. 			{
  200. 				pattern = @"(?:^|\n|\r)[ \t]*End[ \t]+(?:Sub|Function)('|\s|$)";
  201. 				regex = new Regex( pattern, RegexOptions.IgnoreCase );
  202. 				if ( regex.IsMatch( scriptcode ) )
  203. 				{
  204. 					MatchCollection matches = regex.Matches( scriptcode );
  205. 					if ( matches.Count != subroutines.Count )
  206. 					{
  207. 						RedLine( "{0} Sub and Function statements found, against {1} End Sub and End Function statements\n", subroutines.Count, matches.Count );
  208.  
  209. 					}
  210. 					pattern = @"(?:^|\r|\n)\s*(Sub|Function)\s.*?(?:^|\n|\r)[ \t]*End[ \t]+\1('|\s|$)";
  211. 					regex = new Regex( pattern, RegexOptions.Singleline );
  212. 					if ( regex.IsMatch( scriptcode ) )
  213. 					{
  214. 						matches = regex.Matches( scriptcode );
  215. 						foreach ( Match match in matches )
  216. 						{
  217. 							string subroutine = match.Groups[0].ToString( );
  218. 							List<string> subs = new List<string>( );
  219. 							int startsubs = 0;
  220. 							int endsubs = 0;
  221. 							pattern = @"(?:^|\r|\n)\s*(?:Sub|Function)\s(\w+)";
  222. 							regex = new Regex( pattern );
  223. 							if ( regex.IsMatch( subroutine ) )
  224. 							{
  225. 								MatchCollection submatches = regex.Matches( subroutine );
  226. 								startsubs = submatches.Count;
  227. 								foreach ( Match sub in submatches )
  228. 								{
  229. 									subs.Add( sub.Value.Trim( "\n\r\t ".ToCharArray( ) ) );
  230. 								}
  231. 							}
  232. 							pattern = @"[\n\r]+\s*End[ \t]+(Sub|Function)(?:\s|$)";
  233. 							regex = new Regex( pattern );
  234. 							if ( regex.IsMatch( subroutine ) )
  235. 							{
  236. 								MatchCollection submatches = regex.Matches( subroutine );
  237. 								endsubs = submatches.Count;
  238. 							}
  239. 							if ( startsubs > 1 || endsubs > 1 )
  240. 							{
  241. 								RedLine( "Possibly nested or improperly terminated functions and/or subroutines:" );
  242. 								Console.WriteLine( "\t{0}\n", String.Join( "\n\t", subs.ToArray( ) ) );
  243. 							}
  244. 						}
  245. 					}
  246. 				}
  247. 			}
  248.  
  249. 			#endregion Check Subroutine Nesting
  250.  
  251.  
  252. 			#region List Variables
  253.  
  254. 			// Create a list of variables found in the code
  255. 			if ( showvars )
  256. 			{
  257. 				pattern = @"(?:^|\n|\r)[ \t]*Dim[ \t]+([A-Z][^\n\r:]+)";
  258. 				regex = new Regex( pattern, RegexOptions.IgnoreCase );
  259. 				if ( regex.IsMatch( scriptcode ) )
  260. 				{
  261. 					MatchCollection matches = regex.Matches( scriptcode );
  262. 					if ( matches.Count > 0 )
  263. 					{
  264. 						foreach ( Match match in matches )
  265. 						{
  266. 							string[] vars = match.Groups[1].ToString( ).Split( ", ()".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries );
  267. 							foreach ( string var in vars )
  268. 							{
  269. 								bool listed = false;
  270. 								foreach ( string key in subroutines.Keys )
  271. 								{
  272. 									if ( var.ToLower( ) == key.ToLower( ) )
  273. 									{
  274. 										listed = true;
  275. 									}
  276. 								}
  277. 								if ( !listed )
  278. 								{
  279. 									variables[var] = 0;
  280. 									if ( var.Length > columnwidth )
  281. 									{
  282. 										columnwidth = var.Length;
  283. 									}
  284. 								}
  285. 							}
  286. 						}
  287. 					}
  288. 				}
  289. 			}
  290.  
  291. 			#endregion List Variables
  292.  
  293.  
  294. 			#region Count and Display Subroutines Usage
  295.  
  296. 			// Iterate through the list of subroutines and count the occurrences of its name
  297. 			if ( showsubs )
  298. 			{
  299. 				List<string> keys = new List<string>( subroutines.Keys );
  300. 				foreach ( string sub in keys )
  301. 				{
  302. 					bool ignorethissub = !htawindowevents && scriptext == ".hta" && ignoredsubs.Contains( sub.ToLower( ) );
  303. 					if ( !ignorethissub )
  304. 					{
  305. 						pattern = String.Format( @"\b{0}\b", sub );
  306. 						regex = new Regex( pattern, RegexOptions.IgnoreCase );
  307. 						if ( regex.IsMatch( scriptcode ) )
  308. 						{
  309. 							if ( !sub.ToLower( ).StartsWith( "window_on" ) )
  310. 							{
  311. 								subroutines[sub] += regex.Matches( scriptcode ).Count - 1;
  312. 								if ( subroutines[sub] == 0 )
  313. 								{
  314. 									unusedsubs += 1;
  315. 								}
  316. 							}
  317. 						}
  318. 					}
  319. 				}
  320. 				// Show the results
  321. 				if ( unusedonly )
  322. 				{
  323. 					Console.WriteLine( "{0} Unused Subroutine{1}{2}", unusedsubs, ( unusedsubs == 1 ? String.Empty : "s" ), ( unusedsubs == 0 ? String.Empty : ":" ) );
  324. 					Console.WriteLine( "{0}=================={1}{2}", new String( '=', unusedsubs.ToString( ).Length ), ( unusedsubs == 1 ? String.Empty : "=" ), ( unusedsubs == 0 ? String.Empty : "=" ) );
  325.  
  326. 				}
  327. 				else
  328. 				{
  329. 					Console.WriteLine( "{0,-" + columnwidth + "}    Occurrences:", "Subroutine:" );
  330. 					Console.WriteLine( "{0,-" + columnwidth + "}    ============", "===========" );
  331. 				}
  332. 				foreach ( string key in subroutines.Keys )
  333. 				{
  334. 					bool ignorethissub = !htawindowevents && scriptext == ".hta" && ignoredsubs.Contains( key.ToLower( ) );
  335. 					if ( subroutines[key] == 0 )
  336. 					{
  337. 						if ( unusedonly )
  338. 						{
  339. 							if ( !ignorethissub )
  340. 							{
  341. 								Console.WriteLine( key );
  342. 							}
  343. 						}
  344. 						else
  345. 						{
  346. 							if ( ignorethissub )
  347. 							{
  348. 								Console.WriteLine( "{0,-" + columnwidth + "}    {1}", key, subroutines[key] );
  349. 							}
  350. 							else
  351. 							{
  352. 								RedLine( string.Format( "{0,-" + columnwidth + "}    {1}", key, subroutines[key] ) );
  353. 							}
  354. 						}
  355. 						rc += 1;
  356. 					}
  357. 					else if ( !unusedonly )
  358. 					{
  359. 						Console.WriteLine( "{0,-" + columnwidth + "}    {1}", key, subroutines[key] );
  360. 					}
  361. 				}
  362. 				Console.WriteLine( );
  363. 			}
  364.  
  365. 			#endregion Count and Display Subroutines Usage
  366.  
  367.  
  368. 			#region Count and Display Variables Usage
  369.  
  370. 			// Iterate through the list of variables and count the occurrences of its name
  371. 			if ( showvars )
  372. 			{
  373. 				List<string> keys = new List<string>( variables.Keys );
  374. 				foreach ( string variable in keys )
  375. 				{
  376. 					pattern = String.Format( @"\b{0}\b", variable );
  377. 					regex = new Regex( pattern, RegexOptions.IgnoreCase );
  378. 					if ( regex.IsMatch( scriptcode ) )
  379. 					{
  380. 						variables[variable] = regex.Matches( scriptcode ).Count - 1;
  381. 						if ( variables[variable] == 0 )
  382. 						{
  383. 							unusedvars += 1;
  384. 						}
  385. 					}
  386. 				}
  387. 				// Show the results
  388. 				if ( unusedonly )
  389. 				{
  390. 					Console.WriteLine( "{0} Unused Variable{1}{2}", unusedvars, ( unusedvars == 1 ? String.Empty : "s" ), ( unusedvars == 0 ? String.Empty : ":" ) );
  391. 					Console.WriteLine( "{0}================{1}{2}", new String( '=', unusedvars.ToString( ).Length ), ( unusedvars == 1 ? String.Empty : "=" ), ( unusedvars == 0 ? String.Empty : "=" ) );
  392. 				}
  393. 				else
  394. 				{
  395. 					Console.WriteLine( "{0,-" + columnwidth + "}    Occurrences:", "Variable:" );
  396. 					Console.WriteLine( "{0,-" + columnwidth + "}    ============", "=========" );
  397. 				}
  398. 				foreach ( string key in variables.Keys )
  399. 				{
  400. 					if ( variables[key] == 0 )
  401. 					{
  402. 						if ( unusedonly )
  403. 						{
  404. 							Console.WriteLine( key );
  405. 						}
  406. 						else
  407. 						{
  408. 							RedLine( String.Format( "{0,-" + columnwidth + "}    {1}", key, variables[key] ) );
  409. 						}
  410. 						rc += 1;
  411. 					}
  412. 					else if ( !unusedonly )
  413. 					{
  414. 						Console.WriteLine( "{0,-" + columnwidth + "}    {1}", key, variables[key] );
  415. 					}
  416. 				}
  417. 				Console.WriteLine( );
  418. 			}
  419.  
  420. 			#endregion Count and Display Variables Usage
  421.  
  422.  
  423. 			#region Check HTA Head
  424.  
  425. 			if ( showsubs && showvars )
  426. 			{
  427. 				if ( Path.GetExtension( scriptfile ).ToLower( ) == ".hta" )
  428. 				{
  429. 					UnderLine( "HTA Head:" );
  430. 					int htaerrors = 0;
  431. 					pattern = @"<style[^>]*>((?:.|\n|\r)*?)</style>";
  432. 					regex = new Regex( pattern, RegexOptions.IgnoreCase );
  433. 					if ( regex.IsMatch( scriptcode ) )
  434. 					{
  435. 						MatchCollection matches = regex.Matches( scriptcode );
  436. 						if ( matches.Count > 0 )
  437. 						{
  438. 							foreach ( Match match in matches )
  439. 							{
  440. 								foreach ( Group submatch in match.Groups )
  441. 								{
  442. 									htaerrors += CheckStyles( submatch.ToString( ) );
  443. 								}
  444. 							}
  445. 						}
  446. 					}
  447. 					switch ( htaerrors )
  448. 					{
  449. 						case 0:
  450. 							Console.WriteLine( "No CSS errors found" );
  451. 							break;
  452. 						case 1:
  453. 							RedLine( "\n1 possible CSS error found" );
  454. 							break;
  455. 						default:
  456. 							RedLine( "\n{0} possible CSS errors found", htaerrors );
  457. 							break;
  458. 					}
  459. 				}
  460. 			}
  461.  
  462. 			#endregion Check HTA Head
  463.  
  464.  
  465. 			#region Check HTA Event Handlers Case
  466.  
  467. 			if ( showsubs && showvars )
  468. 			{
  469. 				if ( Path.GetExtension( scriptfile ).ToLower( ) == ".hta" )
  470. 				{
  471. 					UnderLine( "\nHTA Event Handlers:" );
  472.  
  473. 					List<string> eventnames = Enum.GetNames( typeof( Events ) ).Cast<string>( ).ToList<string>( );
  474. 					List<string> warnings = new List<string>( );
  475. 					Regex regexci = new Regex( @"\bwindow_onload\b", RegexOptions.IgnoreCase );
  476. 					bool caseissue = false;
  477. 					foreach ( Match match in regexci.Matches( scriptcode ) )
  478. 					{
  479. 						Regex regexcs = new Regex( @"\bwindow_onload\b", RegexOptions.None );
  480. 						if ( !caseissue && regexci.IsMatch( scriptcode ) && !regexcs.IsMatch( match.Value ) )
  481. 						{
  482. 							warnings.Add( match.Value );
  483. 							caseissue = true;
  484. 						}
  485. 					}
  486. 					regexci = new Regex( @"\bwindow_onunload\b", RegexOptions.IgnoreCase );
  487. 					caseissue = false;
  488. 					foreach ( Match match in regexci.Matches( scriptcode ) )
  489. 					{
  490. 						Regex regexcs = new Regex( @"\bwindow_onunload\b", RegexOptions.None );
  491. 						if ( !caseissue && regexci.IsMatch( scriptcode ) && !regexcs.IsMatch( match.Value ) )
  492. 						{
  493. 							warnings.Add( match.Value );
  494. 							caseissue = true;
  495. 						}
  496. 					}
  497. 					foreach ( string eventname in eventnames )
  498. 					{
  499. 						string eventhandler = CheckEvent( eventname, scriptcode );
  500. 						if ( !String.IsNullOrEmpty( eventhandler ) )
  501. 						{
  502. 							warnings.Add( eventname );
  503. 						}
  504. 					}
  505. 					warnings.Sort( );
  506. 					switch ( warnings.Count )
  507. 					{
  508. 						case 0:
  509. 							Console.WriteLine( "No case mismatches for event handlers found" );
  510. 							break;
  511. 						case 1:
  512. 							RedLine( "\n1 possible case mismatch for event handler \"{0}\"", warnings[0] );
  513. 							break;
  514. 						default:
  515. 							foreach ( string warning in warnings )
  516. 							{
  517. 								Console.WriteLine( "Possible case mismatch for event handler \"{0}\"", warning );
  518. 							}
  519. 							RedLine( "\n{0} possible case mismatches for event handlers found", warnings.Count );
  520. 							break;
  521. 					}
  522. 				}
  523. 			}
  524.  
  525. 			#endregion Check HTA Event Handlers Case
  526.  
  527.  
  528. 			return rc;
  529. 		}
  530.  
  531.  
  532. 		static string CheckEvent( string eventname, string code )
  533. 		{
  534. 			string pattern = string.Format( @"\s({0})=", eventname );
  535. 			Regex regexci = new Regex( pattern, RegexOptions.IgnoreCase );
  536. 			if ( regexci.IsMatch( code ) )
  537. 			{
  538. 				MatchCollection matches = regexci.Matches( code );
  539. 				Regex regexcs = new Regex( pattern, RegexOptions.None );
  540. 				foreach ( Match match in matches )
  541. 				{
  542. 					if( match.Groups[1].Value != eventname )
  543. 					{
  544. 						return match.Groups[1].Value;
  545. 					}
  546. 				}
  547.  
  548. 			}
  549. 			return null;
  550. 		}
  551.  
  552.  
  553. 		static int CheckStyle( string styledef )
  554. 		{
  555. 			int errors = 0;
  556. 			string pattern = @"^([^@\{]+)\{([^\}]+)\}";
  557. 			Regex regex = new Regex( pattern );
  558. 			if ( regex.IsMatch( styledef ) )
  559. 			{
  560. 				string tagdef = regex.Match( styledef ).Groups[1].ToString( ).Trim( "\n\r\t ".ToCharArray( ) );
  561. 				string tagstyle = regex.Match( styledef ).Groups[2].ToString( ).Trim( "\n\r\t ".ToCharArray( ) );
  562. 				string[] tagcssall = tagstyle.Split( ';' );
  563. 				for ( int i = 0; i < tagcssall.Length; i++ )
  564. 				{
  565. 					tagcssall[i] = tagcssall[i].Trim( "\n\r\t ".ToCharArray( ) );
  566. 				}
  567. 				string pattern1 = @"^([\w-]+)\s*:\s*([^\n\r\;\{\}]+)$";
  568. 				Regex regex1 = new Regex( pattern1 );
  569. 				string pattern2 = @"^([\w-]+)\s*:";
  570. 				Regex regex2 = new Regex( pattern2 );
  571. 				foreach ( string line in tagcssall )
  572. 				{
  573. 					if ( String.IsNullOrWhiteSpace( line ) )
  574. 					{
  575. 						// No action required
  576. 					}
  577. 					else if ( regex1.IsMatch( line ) )
  578. 					{
  579. 						MatchCollection matches1 = regex1.Matches( line );
  580. 						string csskey = matches1[0].Groups[1].ToString( );
  581. 						string cssval = matches1[0].Groups[2].ToString( );
  582. 						string pattern3 = @"^[^\(]*\)|\([^\)]*$";
  583. 						regex = new Regex( pattern3 );
  584. 						if ( regex.IsMatch( cssval ) )
  585. 						{
  586. 							if ( !csserrors.Contains( csskey ) )
  587. 							{
  588. 								csserrors.Add( csskey );
  589. 								RedLine( "Possible CSS error for {0}:", csskey );
  590. 								Console.WriteLine( "\t{0}\n", cssval );
  591. 								errors += 1;
  592. 							}
  593. 						}
  594. 					}
  595. 					else if ( regex2.IsMatch( line ) )
  596. 					{
  597. 						MatchCollection matches2 = regex2.Matches( line );
  598. 						string csskey = matches2[0].Groups[1].ToString( );
  599. 						if ( !csserrors.Contains( csskey ) )
  600. 						{
  601. 							csserrors.Add( csskey );
  602. 							RedLine( "Possible CSS error(s) for {0}:", csskey );
  603. 							errors += 1;
  604. 						}
  605. 					}
  606. 					else
  607. 					{
  608. 						string csserror = styledef.Substring( 0, styledef.IndexOfAny( "{\n\r".ToCharArray( ) ) ).Trim( "{\n\r\t ".ToCharArray( ) );
  609. 						if ( !csserrors.Contains( csserror ) )
  610. 						{
  611. 							RedLine( "Possible CSS error(s):" );
  612. 							Console.WriteLine( "{0}\n", styledef );
  613. 							errors += 1;
  614. 						}
  615. 					}
  616. 				}
  617. 			}
  618. 			return errors;
  619. 		}
  620.  
  621.  
  622. 		static int CheckStyles( string stylesheet )
  623. 		{
  624. 			int errors = 0;
  625. 			string pattern = @"\/\*(.|\n|\r)*?\*\/";
  626. 			Regex regex = new Regex( pattern );
  627. 			if ( regex.IsMatch( stylesheet ) )
  628. 			{
  629. 				stylesheet = regex.Replace( stylesheet, string.Empty );
  630. 			}
  631. 			pattern = @"[^\n\r\{\}]+\s*\{[^\}]+\}";
  632. 			regex = new Regex( pattern, RegexOptions.IgnoreCase );
  633. 			if ( regex.IsMatch( stylesheet ) )
  634. 			{
  635. 				MatchCollection matches = regex.Matches( stylesheet );
  636. 				foreach ( Match match in matches )
  637. 				{
  638. 					errors += CheckStyle( match.ToString( ) );
  639. 				}
  640. 			}
  641. 			return errors;
  642. 		}
  643.  
  644.  
  645. 		static void RedLine( string line, params object[] rlargs )
  646. 		{
  647. 			Console.ForegroundColor = ConsoleColor.Red;
  648. 			if ( rlargs.Length > 0 )
  649. 			{
  650. 				Console.WriteLine( line, rlargs );
  651. 			}
  652. 			else
  653. 			{
  654. 				Console.WriteLine( line );
  655. 			}
  656. 			Console.ResetColor( );
  657. 		}
  658.  
  659.  
  660. 		static int ShowHelp( params string[] errmsg )
  661. 		{
  662. 			#region Error Message
  663.  
  664. 			if ( errmsg.Length > 0 )
  665. 			{
  666. 				List<string> errargs = new List<string>( errmsg );
  667. 				errargs.RemoveAt( 0 );
  668. 				Console.Error.WriteLine( );
  669. 				Console.ForegroundColor = ConsoleColor.Red;
  670. 				Console.Error.Write( "ERROR:\t" );
  671. 				Console.ForegroundColor = ConsoleColor.White;
  672. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  673. 				Console.ResetColor( );
  674. 			}
  675.  
  676. 			#endregion Error Message
  677.  
  678.  
  679. 			#region Help Text
  680.  
  681. 			/*
  682. 			CheckVarsVBS.exe,  Version 1.05
  683. 			Check VBScript code for unused variables and subroutines
  684.  
  685. 			Usage:    CheckVarsVBS.exe  "vbsfile"  [ /S | /V ]  [ /U ]  [ /W ]
  686.  
  687. 			Where:    "vbsfile"         is the VBScript or HTA file to be examined
  688. 			          /S                tests Subroutines only
  689. 			                            (default: subroutines as well as variables)
  690. 			          /U                list Unused subroutines and variables only
  691. 			                            (default: list all subroutines and variables)
  692. 			          /V                tests Variables only
  693. 			                            (default: subroutines as well as variables)
  694. 			          /W                include Window_On* subroutines for HTAs
  695. 			                            (default: ignore Window_On* subroutines in HTAs)
  696.  
  697. 			Notes:    When checking subroutines, the program will also check for
  698. 			          improperly terminated and nested subroutines.
  699. 			          For HTAs only, the following special subroutines are ignored
  700. 			          (not listed in red, or not at all with /U switch) by default:
  701. 			          Window_OnBeforeUnload, Window_OnBlur, Window_OnFocus,
  702. 			          Window_OnHelp, Window_OnLoad, Window_OnResize, Window_OnUnload;
  703. 			          use /W to treat them as ordinary subroutines.
  704. 			          For HTAs only, unless checking for variables only (/V switch),
  705. 			          this program will search the HTA's head for CSS style definitions,
  706. 			          and check those for some common typos.
  707. 			          The program's return code equals the number of unused subroutines
  708. 			          and/or variables, or -1 in case of (command line) errors.
  709.  
  710. 			Written by Rob van der Woude
  711. 			http://www.robvanderwoude.com
  712. 			*/
  713.  
  714. 			#endregion Help Text
  715.  
  716.  
  717. 			#region Display Help Text
  718.  
  719. 			Console.Error.WriteLine( );
  720.  
  721. 			Console.Error.WriteLine( "CheckVarsVBS.exe,  Version {0}", progver );
  722.  
  723. 			Console.Error.WriteLine( "Check VBScript code for unused variables and subroutines" );
  724.  
  725. 			Console.Error.WriteLine( );
  726.  
  727. 			Console.Error.Write( "Usage:    " );
  728. 			Console.ForegroundColor = ConsoleColor.White;
  729. 			Console.Error.WriteLine( "CheckVarsVBS.exe  \"vbsfile\"  [ /S | /V ]  [ /U ]  [ /W ]" );
  730. 			Console.ResetColor( );
  731.  
  732. 			Console.Error.WriteLine( );
  733.  
  734. 			Console.Error.Write( "Where:    " );
  735. 			Console.ForegroundColor = ConsoleColor.White;
  736. 			Console.Error.Write( "\"vbsfile\"" );
  737. 			Console.ResetColor( );
  738. 			Console.Error.WriteLine( "         is the VBScript or HTA file to be examined" );
  739.  
  740. 			Console.ForegroundColor = ConsoleColor.White;
  741. 			Console.Error.Write( "          /S" );
  742. 			Console.ResetColor( );
  743. 			Console.Error.Write( "                tests " );
  744. 			Console.ForegroundColor = ConsoleColor.White;
  745. 			Console.Error.Write( "S" );
  746. 			Console.ResetColor( );
  747. 			Console.Error.WriteLine( "ubroutines only" );
  748.  
  749. 			Console.Error.WriteLine( "                            (default: subroutines as well as variables)" );
  750.  
  751. 			Console.ForegroundColor = ConsoleColor.White;
  752. 			Console.Error.Write( "          /U" );
  753. 			Console.ResetColor( );
  754. 			Console.Error.Write( "                list " );
  755. 			Console.ForegroundColor = ConsoleColor.White;
  756. 			Console.Error.Write( "U" );
  757. 			Console.ResetColor( );
  758. 			Console.Error.WriteLine( "nused subroutines and variables only" );
  759.  
  760. 			Console.Error.WriteLine( "                            (default: list all subroutines and variables)" );
  761.  
  762. 			Console.ForegroundColor = ConsoleColor.White;
  763. 			Console.Error.Write( "          /V" );
  764. 			Console.ResetColor( );
  765. 			Console.Error.Write( "                tests " );
  766. 			Console.ForegroundColor = ConsoleColor.White;
  767. 			Console.Error.Write( "V" );
  768. 			Console.ResetColor( );
  769. 			Console.Error.WriteLine( "ariables only" );
  770.  
  771. 			Console.Error.WriteLine( "                            (default: subroutines as well as variables)" );
  772.  
  773. 			Console.ForegroundColor = ConsoleColor.White;
  774. 			Console.Error.Write( "          /W" );
  775. 			Console.ResetColor( );
  776. 			Console.Error.Write( "                include " );
  777. 			Console.ForegroundColor = ConsoleColor.White;
  778. 			Console.Error.Write( "W" );
  779. 			Console.ResetColor( );
  780. 			Console.Error.WriteLine( "indow_On* subroutines for HTAs" );
  781.  
  782. 			Console.Error.WriteLine( "                            (default: ignore Window_On* subroutines in HTAs)" );
  783.  
  784. 			Console.Error.WriteLine( );
  785.  
  786. 			Console.Error.WriteLine( "Notes:    When checking subroutines, the program will also check for" );
  787.  
  788. 			Console.Error.WriteLine( "          improperly terminated and nested subroutines." );
  789.  
  790. 			Console.Error.WriteLine( "          For HTAs only, the following special subroutines are ignored" );
  791.  
  792. 			Console.Error.Write( "          (not listed in red, or not at all with " );
  793. 			Console.ForegroundColor = ConsoleColor.White;
  794. 			Console.Error.Write( "/U" );
  795. 			Console.ResetColor( );
  796. 			Console.Error.WriteLine( " switch) by default:" );
  797.  
  798. 			Console.Error.WriteLine( "          Window_OnBeforeUnload, Window_OnBlur, Window_OnFocus," );
  799.  
  800. 			Console.Error.WriteLine( "          Window_OnHelp, Window_OnLoad, Window_OnResize, Window_OnUnload;" );
  801.  
  802. 			Console.Error.Write( "          use " );
  803. 			Console.ForegroundColor = ConsoleColor.White;
  804. 			Console.Error.Write( "/W" );
  805. 			Console.ResetColor( );
  806. 			Console.Error.WriteLine( " to treat them as ordinary subroutines." );
  807.  
  808. 			Console.Error.Write( "          For HTAs only, unless checking for variables only (" );
  809. 			Console.ForegroundColor = ConsoleColor.White;
  810. 			Console.Error.Write( "/V" );
  811. 			Console.ResetColor( );
  812. 			Console.Error.WriteLine( " switch)," );
  813.  
  814. 			Console.Error.WriteLine( "          this program will search the HTA's head for CSS style definitions," );
  815.  
  816. 			Console.Error.WriteLine( "          and check those for some common typos." );
  817.  
  818. 			Console.Error.WriteLine( "          The program's return code equals the number of unused subroutines" );
  819.  
  820. 			Console.Error.WriteLine( "          and/or variables, or -1 in case of (command line) errors." );
  821.  
  822. 			Console.Error.WriteLine( );
  823.  
  824. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  825.  
  826. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  827.  
  828. 			#endregion Display Help Text
  829.  
  830.  
  831. 			return -1;
  832. 		}
  833.  
  834.  
  835. 		static void UnderLine( string text )
  836. 		{
  837. 			Console.WriteLine( text );
  838. 			Console.WriteLine( new string( '=', text.Replace( "\n", "" ).Replace( "\r", "" ).Length ) );
  839. 		}
  840. 	}
  841.  
  842.  
  843. 	public enum Events
  844. 	{
  845. 		onabort,
  846. 		onafterprint,
  847. 		onbeforeprint,
  848. 		onbeforeunload,
  849. 		onblur,
  850. 		oncanplay,
  851. 		oncanplaythrough,
  852. 		onchange,
  853. 		onclick,
  854. 		oncontextmenu,
  855. 		oncopy,
  856. 		oncut,
  857. 		ondblclick,
  858. 		ondrag,
  859. 		ondragend,
  860. 		ondragenter,
  861. 		ondragleave,
  862. 		ondragover,
  863. 		ondragstart,
  864. 		ondrop,
  865. 		ondurationchange,
  866. 		onemptied,
  867. 		onended,
  868. 		onerror,
  869. 		onfocus,
  870. 		onfocusin,
  871. 		onfocusout,
  872. 		onhashchange,
  873. 		oninput,
  874. 		oninvalid,
  875. 		onkeydown,
  876. 		onkeypress,
  877. 		onkeyup,
  878. 		onload,
  879. 		onloadeddata,
  880. 		onloadedmetadata,
  881. 		onloadstart,
  882. 		onmessage,
  883. 		onmousedown,
  884. 		onmouseenter,
  885. 		onmouseleave,
  886. 		onmousemove,
  887. 		onmouseout,
  888. 		onmouseover,
  889. 		onmouseup,
  890. 		onmousewheel,
  891. 		onoffline,
  892. 		ononline,
  893. 		onopen,
  894. 		onpagehide,
  895. 		onpageshow,
  896. 		onpaste,
  897. 		onpause,
  898. 		onplay,
  899. 		onplaying,
  900. 		onpopstate,
  901. 		onprogress,
  902. 		onratechange,
  903. 		onreset,
  904. 		onresize,
  905. 		onscroll,
  906. 		onsearch,
  907. 		onseeked,
  908. 		onseeking,
  909. 		onselect,
  910. 		onshow,
  911. 		onstalled,
  912. 		onstorage,
  913. 		onsubmit,
  914. 		onsuspend,
  915. 		ontimeupdate,
  916. 		ontoggle,
  917. 		onunload,
  918. 		onvolumechange,
  919. 		onwaiting,
  920. 		onwheel
  921. 	}
  922. }
  923.  

page last uploaded: 2021-01-27, 16:12