Wednesday, 17 September 2008

Generic Code Generator

Came across a useful code/password generator example for strong passwords at this site:

Obviex Password Example

I needed a random token generator for unit tests I wrote, so I extended it to do the following:

  • Generate Alphabetical Code
  • Generate Alphabetical Lower Case Code
  • Generate Alphabetical Upper Case Code
  • Generate Numerical Code

The code can be easily extended to include other combinations and variations.

   1: #region Usings
   2: using System;
   3: using System.Collections.Generic;
   4: using System.Linq;
   5: using System.Security.Cryptography;
   6: #endregion Usings
   7:  
   8: namespace AimKai.Core.Util
   9: {
  10:     /// <summary>
  11:     /// Random code generator
  12:     /// </summary>
  13:     public class RandomCodeGenerator
  14:     {
  15:         #region Constants
  16:  
  17:         /// <summary>
  18:         /// Default minimum code length
  19:         /// </summary>
  20:         private const int DefaultMinCodeLength = 8;
  21:  
  22:         /// <summary>
  23:         /// Default maximum code length
  24:         /// </summary>
  25:         private const int DefaultMaxCodeLength = 10;
  26:  
  27:         /// <summary>
  28:         /// Character set for lower case letters
  29:         /// </summary>
  30:         private const string CodeCharsLcase = "abcdefghijklmnopqrstuvwxyz";
  31:  
  32:         /// <summary>
  33:         /// Character set for upper case letters
  34:         /// </summary>
  35:         private const string CodeCharsUcase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  36:  
  37:         /// <summary>
  38:         /// Character set for numerals
  39:         /// </summary>
  40:         private const string CodeNumerals = "0123456789";
  41:  
  42:         /// <summary>
  43:         /// Character set for specials
  44:         /// </summary>
  45:         private const string CodeCharsSpecial = "*$-+?_&=!%{}/";
  46:  
  47:         /// <summary>
  48:         /// Character set for non ambiguous lower cased letters
  49:         /// </summary>
  50:         private const string CodeCharsLcaseNonambig = "abcdefgijkmnopqrstwxyz";
  51:  
  52:         /// <summary>
  53:         /// Character set for non ambiguous upper cased letters
  54:         /// </summary>
  55:         private const string CodeCharsUcaseNonambig = "ABCDEFGHJKLMNPQRSTWXYZ";
  56:  
  57:         /// <summary>
  58:         /// Character set for non ambiguous letters
  59:         /// </summary>
  60:         private const string CodeNumeralsNonambig = "23456789";
  61:  
  62:         #endregion Constants
  63:  
  64:         #region Public Methods
  65:  
  66:         /// <summary>
  67:         /// Generates an alphanumeric random code between 8 and 10 characters
  68:         /// </summary>
  69:         /// <returns>Random code</returns>
  70:         public static string Generate ()
  71:         {
  72:             return Generate(DefaultMinCodeLength, DefaultMaxCodeLength, false, false, false, true, false, false);
  73:         }
  74:  
  75:         /// <summary>
  76:         /// Generates an alphanumeric random with passed minimum length and a maximum of 10 characters 
  77:         /// </summary>
  78:         /// <param name="minLength">Minimum length</param>
  79:         /// <returns>Random Code</returns>
  80:         public static string Generate(int minLength)
  81:         {
  82:             CheckParameters(minLength);
  83:             return Generate(minLength, minLength, false, false, false, true, false, false);
  84:         }
  85:  
  86:         /// <summary>
  87:         /// Generates an alphanumeric random with passed minimum and maximum lengths
  88:         /// </summary>
  89:         /// <param name="minLength">Minimum length</param>
  90:         /// <param name="maxLength">Maximum length</param>
  91:         /// <returns>Random Code</returns>
  92:         public static string Generate(int minLength, int maxLength)
  93:         {
  94:             CheckParameters(minLength, maxLength);
  95:             return Generate(minLength, maxLength, false, false, false, true, false, false);
  96:         }
  97:  
  98:         /// <summary>
  99:         /// Generate alphabetical code
 100:         /// </summary>
 101:         /// <returns>Random code</returns>
 102:         public static string GenerateAlphaOnly()
 103:         {
 104:             return Generate(DefaultMinCodeLength, DefaultMaxCodeLength, true, false, false, true, false, false);
 105:         }
 106:  
 107:         /// <summary>
 108:         /// Generate alphabetical code with passed length
 109:         /// </summary>
 110:         /// <param name="minLength">Minimum length</param>
 111:         /// <returns>Code</returns>
 112:         public static string GenerateAlphaOnly(int minLength)
 113:         {
 114:             CheckParameters(minLength);
 115:             return Generate(minLength, minLength, true, false, false, true, false, false);
 116:         }
 117:  
 118:         /// <summary>
 119:         /// Generate alphabetical code with passed length
 120:         /// </summary>
 121:         /// <param name="minLength">Minimum length</param>
 122:         /// <param name="maxLength">Maximum length</param>
 123:         /// <returns>Code</returns>
 124:         public static string GenerateAlphaOnly(int minLength, int maxLength)
 125:         {
 126:             CheckParameters(minLength, maxLength);
 127:             return Generate(minLength, maxLength, true, false, false, true, false, false);
 128:         }
 129:  
 130:         /// <summary>
 131:         /// Generate lower case alphabetical code
 132:         /// </summary>
 133:         /// <returns>Random code</returns>
 134:         public static string GenerateLowerCaseAlphaOnly()
 135:         {
 136:             return Generate(DefaultMinCodeLength, DefaultMaxCodeLength, true, false, false, true, true, false);
 137:         }
 138:  
 139:         /// <summary>
 140:         /// Generate lower case alphabetical code with passed minimum length
 141:         /// </summary>
 142:         /// <param name="minLength">Minimum length</param>
 143:         /// <returns>Code</returns>
 144:         public static string GenerateLowerCaseAlphaOnly(int minLength)
 145:         {
 146:             CheckParameters(minLength);
 147:             return Generate(minLength, minLength, true, false, false, true, true, false);
 148:         }
 149:  
 150:         /// <summary>
 151:         /// Generate lower case alphabetical code with passed minimum and maximum length 
 152:         /// </summary>
 153:         /// <param name="minLength">Minimum length</param>
 154:         /// <param name="maxLength">Maximum length</param>
 155:         /// <returns>Code</returns>
 156:         public static string GenerateLowerCaseAlphaOnly(int minLength, int maxLength)
 157:         {
 158:             CheckParameters(minLength, maxLength);
 159:             return Generate(minLength, maxLength, true, false, false, true, true, false);
 160:         }
 161:  
 162:         /// <summary>
 163:         /// Generate upper case alphabetical code
 164:         /// </summary>
 165:         /// <returns>Random code</returns>
 166:         public static string GenerateUpperCaseAlphaOnly()
 167:         {
 168:             return Generate(DefaultMinCodeLength, DefaultMaxCodeLength, true, false, false, true, false, true);
 169:         }
 170:  
 171:         /// <summary>
 172:         /// Generate lower case alphabetical code with passed minimum length
 173:         /// </summary>
 174:         /// <param name="minLength">Minimum length</param>
 175:         /// <returns>Code</returns>
 176:         public static string GenerateUpperCaseAlphaOnly(int minLength)
 177:         {
 178:             CheckParameters(minLength);
 179:             return Generate(minLength, minLength, true, false, false, true, false, true);
 180:         }
 181:  
 182:         /// <summary>
 183:         /// Generate lower case alphabetical code with passed minimum and maximum length 
 184:         /// </summary>
 185:         /// <param name="minLength">Minimum length</param>
 186:         /// <param name="maxLength">Maximum length</param>
 187:         /// <returns>Code</returns>
 188:         public static string GenerateUpperCaseAlphaOnly(int minLength, int maxLength)
 189:         {
 190:             CheckParameters(minLength, maxLength);
 191:             return Generate(minLength, maxLength, true, false, false, true, false, true);
 192:         }
 193:  
 194:         /// <summary>
 195:         /// Generate numerical code
 196:         /// </summary>
 197:         /// <returns>Random code</returns>
 198:         public static string GenerateNumericsOnly()
 199:         {
 200:             return Generate(DefaultMinCodeLength, DefaultMaxCodeLength, false, true, false, true,
 201:                              false, false);
 202:         }
 203:  
 204:         /// <summary>
 205:         /// Generate numerical code with minimum length
 206:         /// </summary>
 207:         /// <param name="minLength">Minimum length</param>
 208:         /// <returns>Random code</returns>
 209:         public static string GenerateNumericsOnly(int minLength)
 210:         {
 211:             CheckParameters(minLength);
 212:             return Generate(minLength, minLength, false, true, false, true,
 213:                              false, false);
 214:         }
 215:  
 216:         /// <summary>
 217:         /// Generate numerical code with maximum length
 218:         /// </summary>
 219:         /// <param name="minLength">Minimum length</param>
 220:         /// <param name="maxLength">Maximum length</param>
 221:         /// <returns>Random code</returns>
 222:         public static string GenerateNumericsOnly(int minLength, int maxLength)
 223:         {
 224:             CheckParameters(minLength, maxLength);
 225:             return Generate(minLength, maxLength, false, true, false, true, 
 226:                              false, false);
 227:         }
 228:  
 229:         /// <summary>
 230:         /// Generate strong password
 231:         /// </summary>
 232:         /// <returns>Strong password</returns>
 233:         public static string GenerateStrongPassword()
 234:         {
 235:             return Generate(DefaultMinCodeLength, DefaultMaxCodeLength, false, false, true, false,
 236:                             false, false);
 237:         }
 238:  
 239:         #endregion Public Methods
 240:  
 241:         /// <summary>
 242:         /// Generate code based on passed parameters
 243:         /// </summary>
 244:         /// <param name="minLength">Minimum length</param>
 245:         /// <param name="maxLength">Maximum length</param>
 246:         /// <param name="onlyLetters">Only letters</param>
 247:         /// <param name="onlyNumbers">Only numbers</param>
 248:         /// <param name="isStrong">Is strong password</param>
 249:         /// <param name="useAmbiguous">Use ambigous letters</param>
 250:         /// <param name="useLowerCaseOnly">Use lower case letters</param>
 251:         /// <param name="useUpperCaseOnly">Use upper case lettters</param>
 252:         /// <returns>Code</returns>
 253:         private static string Generate(int minLength, int maxLength, bool onlyLetters, bool onlyNumbers,
 254:             bool isStrong, bool useAmbiguous, bool useLowerCaseOnly, bool useUpperCaseOnly)
 255:         {           
 256:             //Determine what character groups 
 257:             var charGroups = DetermineCharGroups(isStrong, onlyLetters, useLowerCaseOnly, useAmbiguous, useUpperCaseOnly, onlyNumbers);
 258:  
 259:             // Use this array to track the number of unused characters in each
 260:             // character group.
 261:             var charsLeftInGroup = new int[charGroups.Length];
 262:  
 263:             // Initially, all characters in each group are not used.
 264:             for (var i = 0; i < charsLeftInGroup.Length; i++)
 265:                 charsLeftInGroup[i] = charGroups[i].Length;
 266:  
 267:             // Use this array to track (iterate through) unused character groups.
 268:             var leftGroupsOrder = new int[charGroups.Length];
 269:  
 270:             // Initially, all character groups are not used.
 271:             for (var i = 0; i < leftGroupsOrder.Length; i++)
 272:                 leftGroupsOrder[i] = i;
 273:  
 274:             // Generate random seed for random letter/numeral
 275:             var seed = GenerateSeed();
 276:  
 277:             // Now, this is real randomization.
 278:             var random = new Random(seed);
 279:  
 280:             // Allocate appropriate memory for the code.
 281:             var code = minLength < maxLength ? new char[random.Next(minLength, maxLength + 1)] : new char[minLength];
 282:  
 283:             // Index of the last non-processed group.
 284:             var lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
 285:  
 286:             // Generate code characters one at a time.
 287:             for (var i = 0; i < code.Length; i++)
 288:             {
 289:                 // If only one character group remained unprocessed, process it;
 290:                 // otherwise, pick a random character group from the unprocessed
 291:                 // group list. To allow a special character to appear in the
 292:                 // first position, increment the second parameter of the Next
 293:                 // function call by one, i.e. lastLeftGroupsOrderIdx + 1.
 294:                 int nextLeftGroupsOrderIdx;
 295:                 if (lastLeftGroupsOrderIdx == 0)
 296:                     nextLeftGroupsOrderIdx = 0;
 297:                 else
 298:                     nextLeftGroupsOrderIdx = random.Next(0,
 299:                                                          lastLeftGroupsOrderIdx);
 300:  
 301:                 // Get the actual index of the character group, from which we will
 302:                 // pick the next character.
 303:                 var nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
 304:  
 305:                 // Get the index of the last unprocessed characters in this group.
 306:                 var lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
 307:  
 308:                 // If only one unprocessed character is left, pick it; otherwise,
 309:                 // get a random character from the unused character list.
 310:                 var nextCharIdx = lastCharIdx == 0 ? 0 : random.Next(0, lastCharIdx + 1);
 311:  
 312:                 // Add this character to the code.
 313:                 code[i] = charGroups[nextGroupIdx][nextCharIdx];
 314:  
 315:                 // If we processed the last character in this group, start over.
 316:                 if (lastCharIdx == 0)
 317:                     charsLeftInGroup[nextGroupIdx] =
 318:                                               charGroups[nextGroupIdx].Length;
 319:                 // There are more unprocessed characters left.
 320:                 else
 321:                 {
 322:                     // Swap processed character with the last unprocessed character
 323:                     // so that we don't pick it until we process all characters in
 324:                     // this group.
 325:                     if (lastCharIdx != nextCharIdx)
 326:                     {
 327:                         var temp = charGroups[nextGroupIdx][lastCharIdx];
 328:                         charGroups[nextGroupIdx][lastCharIdx] =
 329:                                     charGroups[nextGroupIdx][nextCharIdx];
 330:                         charGroups[nextGroupIdx][nextCharIdx] = temp;
 331:                     }
 332:                     // Decrement the number of unprocessed characters in
 333:                     // this group.
 334:                     charsLeftInGroup[nextGroupIdx]--;
 335:                 }
 336:  
 337:                 // If we processed the last group, start all over.
 338:                 if (lastLeftGroupsOrderIdx == 0)
 339:                     lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
 340:                 // There are more unprocessed groups left.
 341:                 else
 342:                 {
 343:                     // Swap processed group with the last unprocessed group
 344:                     // so that we don't pick it until we process all groups.
 345:                     if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
 346:                     {
 347:                         var temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
 348:                         leftGroupsOrder[lastLeftGroupsOrderIdx] =
 349:                                     leftGroupsOrder[nextLeftGroupsOrderIdx];
 350:                         leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
 351:                     }
 352:                     // Decrement the number of unprocessed groups.
 353:                     lastLeftGroupsOrderIdx--;
 354:                 }
 355:             }
 356:  
 357:             return new string(code);
 358:         }
 359:  
 360:         /// <summary>
 361:         /// Generate seed
 362:         /// </summary>
 363:         /// <returns>Seed</returns>
 364:         private static int GenerateSeed()
 365:         {
 366:             var randomBytes = new byte[4];
 367:             var rng = new RNGCryptoServiceProvider();
 368:             rng.GetBytes(randomBytes);
 369:  
 370:             // Convert 4 bytes into a 32-bit integer value.
 371:             return (randomBytes[0] & 0x7f) << 24 |
 372:                    randomBytes[1] << 16 |
 373:                    randomBytes[2] << 8 |
 374:                    randomBytes[3];
 375:         }
 376:  
 377:         /// <summary>
 378:         /// Determine character groups
 379:         /// </summary>
 380:         /// <param name="isStrong">Is strong password</param>
 381:         /// <param name="onlyLetters">Only letters</param>
 382:         /// <param name="useLowerCaseOnly">Lower case letters</param>
 383:         /// <param name="useAmbiguous">Ambiguous</param>
 384:         /// <param name="useUpperCaseOnly">Upper case letters</param>
 385:         /// <param name="onlyNumbers">Only numbers</param>
 386:         /// <returns>Character set</returns>
 387:         private static char[][] DetermineCharGroups(bool isStrong, bool onlyLetters, bool useLowerCaseOnly, bool useAmbiguous, bool useUpperCaseOnly, bool onlyNumbers)
 388:         {
 389:             IList<char[]> charGroups = new List<char[]>();
 390:  
 391:             if (isStrong)
 392:             {
 393:                 charGroups.Add(CodeCharsLcaseNonambig.ToCharArray());
 394:                 charGroups.Add(CodeNumeralsNonambig.ToCharArray());
 395:                 charGroups.Add(CodeCharsUcaseNonambig.ToCharArray());
 396:                 charGroups.Add(CodeCharsSpecial.ToCharArray());
 397:             }
 398:             else if ((onlyLetters) && (useLowerCaseOnly) && (!useAmbiguous))
 399:             {
 400:                 charGroups.Add(CodeCharsLcaseNonambig.ToCharArray());
 401:             }
 402:             else if ((onlyLetters) && (useLowerCaseOnly))
 403:             {
 404:                 charGroups.Add(CodeCharsLcase.ToCharArray());
 405:             }
 406:             else if ((onlyLetters) && (useUpperCaseOnly) && (!useAmbiguous))
 407:             {
 408:                 charGroups.Add(CodeCharsUcaseNonambig.ToCharArray());
 409:             }
 410:             else if ((onlyLetters) && (useUpperCaseOnly))
 411:             {
 412:                 charGroups.Add(CodeCharsUcase.ToCharArray());
 413:             }
 414:             else if (onlyLetters)
 415:             {
 416:                 charGroups.Add(CodeCharsLcase.ToCharArray());
 417:                 charGroups.Add(CodeCharsUcase.ToCharArray());
 418:             }
 419:             else if ((onlyNumbers) && (!useAmbiguous))
 420:             {
 421:                 charGroups.Add(CodeNumeralsNonambig.ToCharArray());
 422:             }
 423:             else if (onlyNumbers)
 424:             {
 425:                 charGroups.Add(CodeNumerals.ToCharArray());
 426:             }
 427:             else if (!useAmbiguous)
 428:             {
 429:                 charGroups.Add(CodeCharsLcaseNonambig.ToCharArray());
 430:                 charGroups.Add(CodeCharsUcaseNonambig.ToCharArray());
 431:                 charGroups.Add(CodeNumeralsNonambig.ToCharArray());                
 432:             }
 433:             else
 434:             {
 435:                 charGroups.Add(CodeCharsLcase.ToCharArray());
 436:                 charGroups.Add(CodeCharsUcase.ToCharArray());
 437:                 charGroups.Add(CodeNumerals.ToCharArray());                
 438:             }
 439:  
 440:             return charGroups.ToArray();
 441:  
 442:         }
 443:  
 444:         /// <summary>
 445:         /// Check parameters for minimum length
 446:         /// </summary>
 447:         /// <param name="minimumLength">Minimum length</param>
 448:         private static void CheckParameters(int minimumLength)
 449:         {
 450:             if (minimumLength <= 0)
 451:                 throw new Exception(string.Format("Must have a positive minimum length. Length passed was '{0}'",,
 452:                                         minimumLength));
 453:         }
 454:  
 455:         /// <summary>
 456:         /// Check parameters for maximum length
 457:         /// </summary>
 458:         /// <param name="minimumLength">Minimum length</param>
 459:         /// <param name="maximumLength">Maximum length</param>
 460:         private static void CheckParameters(int minimumLength, int maximumLength)
 461:         {
 462:             CheckParameters(minimumLength);
 463:  
 464:             if (maximumLength<= minimumLength)
 465:                 throw new Exception(string.Format("Must have a maximum length the same or longer than the minimum length. Maximum length '{0}' and Minimum Length '{1}'.",
 466:                     minimumLength, maximumLength));                    
 467:         }
 468:     }
 469: }

Monday, 18 August 2008

Exporting data as a CSV and allow download from browser C#

I recently did some work to export a data table as a Comma Separated Variable file or a MDB file.

The following code allows you to generate a csv from a data table.

   1: public static void CreateCSVHelper(DataTable sourceTable)
   2: {
   3:     //locals
   4:     StringBuilder outputBuilder = new StringBuilder();
   5:     
   6:     //write column names        
   7:     for (int i = 0; i < sourceTable.Columns.Count; i++)
   8:     {
   9:         if (i > 0)
  10:             outputBuilder.Append(",");
  11:         outputBuilder.Append(sourceTable.Columns[i].ColumnName);        
  12:     }
  13:     outputBuilder.Append(Environment.NewLine);
  14:     
  15:     //Put in data
  16:     foreach (DataRow row in sourceTable.Rows)
  17:     {
  18:         for (int i = 0; i < sourceTable.Columns.Count; i++)
  19:         {       
  20:             if (i > 0)
  21:                 outputBuilder.Append(",");                     
  22:             outputBuilder.Append(string.Format("\"{0}\"",row[i].ToString()));           
  23:         }
  24:         
  25:         outputBuilder.Append(Environment.NewLine);
  26:     }
  27:  
  28:     try
  29:     {
  30:         //Attempt to write file
  31:         StreamWriter sw = new StreamWriter(filename);
  32:         sw.Write(outputBuilder.ToString());
  33:         sw.Close();
  34:     }
  35:     catch (Exception ex)
  36:     {
  37:         System.Diagnostics.Debug.Write(ex);
  38:     }
  39: }

To display a link through to a browser, i.e. provide a link on a page where the user can click, get prompted do you wish to open or save this file – put the following in the code behind of the relevant page.

   1: protected void btnExportCSV_onClick(object sender, EventArgs e)
   2: {
   3:     //Clear buffer
   4:     Response.Clear();
   5:  
   6:     //Tell the browser it expects to get text output in the form of a csv
   7:     Response.ContentType = "text/csv";
   8:  
   9:     //Append header to tell the browser to expect a file
  10:     Response.AppendHeader("Content-Disposition", string.Format("attachment; filename={0}", filename));
  11:     
  12:     //Send file to browser response stream
  13:     Response.TransmitFile(filepath);
  14:  
  15:     //End the response 
  16:     Response.End();
  17: }

Finally if you are trying to use the code inside an update panel you will need to set the export button as a postback trigger. This can either be done using the following asp.net markup:

   1: <asp:UpdatePanel ID="upExport" runat="server">  
   2:     <ContentTemplate>  
   3:         <asp:LinkButton ID="btnExportCSV" runat="server">Export To Excel</asp:LinkButton>  
   4:     </ContentTemplate>  
   5:     <Triggers>  
   6:         <asp:PostBackTrigger ControlID="btnExportCSV">  
   7:         </asp:PostBackTrigger>  
   8:     </Triggers>  
   9: </asp:UpdatePanel>  

or you can set it dynamically in the code behind with the following lines put into the page_load event.


   1: //Deal with postback 
   2: smExportCSV.RegisterPostBackControl(btnExportCSV);


Where smExportCSV is your script manager control.

Friday, 25 July 2008

How do i get code to display in my blog without text going bizarre

Use the
<pre>
tag :)

Added this to my stylesheet of the blog template

pre {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}

and then anything like code can go in <pre></pre> tags and will be left alone by the browser.

Monday, 14 July 2008

Example of a simple static logger class using log4net

I recently had to knock together a very simple logging class for a simple application I was creating to monitor some website activity. My favourite logging application by far is log4net!!

Apache Log4Net

This is a simple static class which can be called anywhere else in the solution. In effect it is just a wrapper. The way that log4net is designed you can attach a logger to any class in your framework. But for simple projects this is a bit overkill.

   1: /// <summary> 
   2: /// Static class logger using Log4Net
   3: /// </summary> 
   4: public static class ExampleLogger 
   5: { 
   6:     #region Members 
   7:  
   8:     /// <summary> 
   9:     /// Create a logger for this static class
  10:     /// </summary> 
  11:     private static readonly ILog logger = LogManager.GetLogger(typeof(ExampleLogger)); 
  12:  
  13:     #endregion Members 
  14:  
  15:     #region Constructors 
  16:  
  17:     /// <summary> 
  18:     /// On construct - build logger object 
  19:     /// </summary> 
  20:     static ExampleLogger() 
  21:     { 
  22:         XmlConfigurator.Configure(); 
  23:     } 
  24:  
  25:     #endregion Constructors 
  26:  
  27:     #region Class Methods 
  28:  
  29:     /// <summary> 
  30:     /// Write information to log 
  31:     /// </summary> 
  32:     /// <param name="logLevel">Level of information to write</param> 
  33:     /// <param name="message">Information to write to log</param> 
  34:     public static void WriteLog(LogLevel logLevel, String message) 
  35:     { 
  36:         if (logLevel.Equals(LogLevel.Debug)) 
  37:         { 
  38:             logger.Debug(message); 
  39:         } 
  40:         else if (logLevel.Equals(LogLevel.Error)) 
  41:         { 
  42:             logger.Error(message); 
  43:         } 
  44:         else if (logLevel.Equals(LogLevel.Fatal)) 
  45:         { 
  46:             logger.Fatal(message); 
  47:         } 
  48:         else if (logLevel.Equals(LogLevel.Info)) 
  49:         { 
  50:             logger.Info(message); 
  51:         } 
  52:         else if (logLevel.Equals(LogLevel.Warn)) 
  53:         { 
  54:             logger.Warn(message); 
  55:         } 
  56:     } 
  57:  
  58:     #endregion Class Methods 
  59: } 
  60:  
  61: /// <summary> 
  62: /// Priority level of the information to be logged 
  63: /// </summary> 
  64: public enum LogLevel 
  65: { 
  66:     Debug = 1, 
  67:     Error, 
  68:     Fatal, 
  69:     Info, 
  70:     Warn 
  71: }

You also need to set where the log information is configured in your web config file at the entry point of your application. I.e. either main or Global.asax etc.

   1: //Configuration for Log4Net
   2: XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));

Finally you need to add the log4net configuration section in the web.config



   1: <!-- Log 4 Net logging -->
   2:  <log4net>
   3:  
   4:    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
   5:      <file value="C:\Log\ExampleLog" />
   6:      <appendToFile value="true" />
   7:      <staticLogFileName value="false" />
   8:      <rollingStyle value="Composite" />
   9:      <datePattern value="yyyyMMdd.lo\g" />
  10:      <maxSizeRollBackups value="10" />
  11:      <maximumFileSize value="1MB" />
  12:      <layout type="log4net.Layout.PatternLayout">
  13:        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
  14:      </layout>
  15:    </appender>
  16:  
  17:    <root>
  18:      <level value="DEBUG" />
  19:      <appender-ref ref="RollingFileAppender" />
  20:    </root>
  21:    
  22:  </log4net>

This configuration sections will log information to a file named ExampleLog and a data pattern inserted. Each day a new file will be created. As if the log file exceeds 1MB.

For more examples for configurations for log4Net – see the website:

Log4Net Configuration Examples

Tuesday, 10 June 2008

Trust your PGP Keys

I spent ages working out why I could get my c# code working with GnuPGP - when i dug deeper it was very simple - it was the fact that i wasn't very trusting.

You need to trust public keys when you sign then! You can be ultimately trusting by setting to level of 5!

GNU Privacy Guard commands

gpg -u [Local User with Private Key] --passphrase [Local user passphrase] --edit-key [Remote user with Public Key] trust

You get 5 options!

You can see the trust later if you do a gpg -vv -k

Monday, 2 June 2008

Problem with connection to Sql Server 2008 with NHibernate

Got exception:

----> NHibernate.ADOException : Could not execute query
----> NHibernate.ADOException : cannot open connection
----> NHibernate.ADOException : Could not create connection from Driver
----> System.Data.SqlClient.SqlException : A connection was successfully established with the server, but then an error occurred during the login process. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)


Enabling Remote Connections in SQL Server 2008 - remembered from before that the SQL Server Surface Configuration Tool is not part of 2008.

It has been replace with the SQL Server Configuration Manager. I personally find the old version to be more user-friendly, but either way, it gets the job done. To enable remote connections in SQL Server 2008:

1. Open the SQL Server Configuration Manager (Start > SQL Server 2008 > Configuration Tools > SQL Server Configuration Manager
2. Navigate to the SQL Server Network Configuration > Protocols for MSSQLSERVER node in the tree view
3. Enable TCP/IP and Named Pipes (you’ll be warned that these changes will not apply until you the service is shut down)
4. Restart the SQL Server Service

This did not work :(

Checked the application log and found this:

Login failed for user 'exampleLogin'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: ]

Open DB in Microsoft Management Studio, click properties and select Security Page and change option.

Another restart of the sql service is required.

:)

Thursday, 22 May 2008

VSS Keywords

Very useful link to keywords used in code managed by sourcesafe.

http://msdn.microsoft.com/en-us/library/d826hy97(VS.80).aspx

Tuesday, 20 May 2008

XPath/XQuery SQL counting repeatable nodes in SQL Server 2005

XML is represented in a field, vchr_Xml on table A, trying to count entities - can use xpath in the sql/xquery to get the count of repeatable nodes.

select convert(int, convert(varchar(max),
convert(xml,{a.ntext_xmlRepresentation).query('count(/Entities/Entity)')))

from [DB].dbo.tbl_A A where A.uid_id = [GUID]

Friday, 16 May 2008

How to add GNU Privacy Guard commands to environment variables Windows

Right-Click on MY COMPUTER, select PROPERTIES, then select the ADVANCED tab.

Click on ENVIRONMENT VARIABLES then select PATH in the top box.
Highlight PATH in the bottom box.

Click EDIT and at the end of the line, type ";C:\Program Files\GnuPG\;" without the quotes but including the semi-colons. Where I have used "C:\Program Files", you should put the path where you installed GnuPG.

This will allow you to open the command prompt (START > RUN > CMD) and simply type "gpg" followed by the command switch to use the advanced features of GnuPG.

NB: you may want to put in C:\Program Files (x86) if you have a 64 bit machine.

Friday, 9 May 2008

Gnu Privacy Guard Commands

GNU Privacy Guard (GPG) commands


http://www.gnupg.org/

This blog lists a load of gpg commands which are really useful!

Useful commands


What follows is a list of useful commands

Help (listing all available commands and options)

gpg --help

We get a full list of commands. Note all gpg commands take the format:

gpg [option1, option2, .. option n] [command] [Filename or user to work with]

Listing keys on keyrings

gpg -k (gpg --list-keys)

lists all public keys on the current users public keyring

gpg --list-secret-keys

lists all secret keys on the current users secret keyring

Generating a new private-public key

gpg --gen-key

Select the kind of key, size of encryption, and other details and give the key pair a name.

Importing a public key onto the keyring

Note you can import private keys this way as well.

gpg –import

Removing a key from the keyring

The following commands remove keys from the respective keyrings. Note if you try and remove a public key which has the same private pair then you will need to remove the private (secret) key first.

Public: gpg --delete-keys [Keyname]
Secret: gpg --delete-secret-keys [Keyname]

Exporting Public Key
To make key available for other users to decrypt with you can export the public key by using the command:

gpg -a -u [Local user with private key] --passphrase [Local user pass phrase] --export >[Name of file for exported public key]


Encrypting data

You can encrypt data with a private key using the following command

gpg -e -o [outputfilename] -u [Local Private Key User] [inputFilename]
gpg -e --output [outputfilename] -u [Local Private Key User] [inputFilename]

You can also armour the output with ascii with the following command:

gpg -ea -o [outputfilename] -u [Local Private Key User] [inputFilename]

Armouring makes the encrypted file more readable in text viewers.

If you omit the -o then it will save the file with an appended extension of .gpg

Decrypting data

The following commands can decrypt data encrypted by a specific public key. Note you need the public key of the pair which the private key was used to encrypt the data with.

eg. gpg -da -r [Public Key] [EncryptedFileName] >[NewFileName]

Note if you omit the pipe to the new file name then the decrypted output will be displayed to the screen.

You need to provide a pass phrase to decipher the encrypted file. You will either be prompted for this or you can use the –passphrase switch

eg. gpg -da --passphrase [PassPhrase] -r [Public Key] [EncryptedFileName] >[NewFileName]
Signing keys

When importing in public keys from the client to your public keyring you must sign the key. This can be done by

gpg -u [Local User with Private Key] --passphrase [Local user passphrase] --edit-key [Remote user with Public Key] sign

You will then need to hit yes and then quit to exit

Very Verbose messages :)

Always useful to get as much information returned back when having problems, Use the -vv (very verbose) option.

For example when you listing key information using the -vv option highlights if the public key has been signed.


Very useful resouces:

Justin Millers Guide
Click here to view