Luhn algorithm validation via a CustomValidator control

The Luhn algorithm is a checksum used for credit cards and many other identifying numbers as a basic integrity validation check.  It’s useful for credit card forms because it avoids unneeded transaction attempts when card numbers are mis-typed.
It’s easy to add an account # Luhn checksum validation control to credit card forms in ASP.Net:
  • Add this method to your business logic.
  • Add a <asp:CustomValidator  … /> control with the error message, target control, etc.
  • Add and wire up a void ServerValidation method:
void ServerValidation(object source, ServerValidateEventArgs args) {
// use a RequiredFieldValidator to check for an empty value
 if (txtCardNum.Text == string.Empty) args.IsValid = true;
 args.IsValid = IsCreditCardValid(this.txtCardNum.Text);
}
 
protected override void OnInit(EventArgs e)    {
 base.OnInit(e);
 valLunCode.ServerValidate += ServerValidation;
}
  • (Optional:) For client-side code, use a Javascript version from here.

Quickly open an app in Terminal

To open an app in terminal, type open -a AppName or open /Applications/AppName.app if you want to specify the path. I use it for starting VNC server via SSH.

Bonus:  echo “set completion-ignore-case On” > ~/.inputrc will make auto-completion case-insensitive.

Correct photo orientation using EXIF data with C#

When processing photos, sometimes you want to re-orient the photo according the orientation recorded by the camera (such as the iPhone’s accelerometer) and stored in the EXIF meta data.  It’s easy to do:

// Rotate the image according to EXIF data
var bmp = new Bitmap(pathToImageFile);
var exif = new EXIFextractor(ref bmp, "\n"); // get source from http://www.codeproject.com/KB/graphics/exifextractor.aspx?fid=207371
 
if (exif["Orientation"] != null)
{
RotateFlipType flip = OrientationToFlipType(exif["Orientation"].ToString());
 
if (flip != RotateFlipType.RotateNoneFlipNone) // don't flip of orientation is correct
{
bmp.RotateFlip(flip);
exif.setTag(0x112, "1"); // Optional: reset orientation tag
bmp.Save(pathToImageFile, ImageFormat.Jpeg);
}
 
// Match the orientation code to the correct rotation:
 
private static RotateFlipType OrientationToFlipType(string orientation)
{
switch (int.Parse(orientation))
{
case 1:
return RotateFlipType.RotateNoneFlipNone;
break;
case 2:
return RotateFlipType.RotateNoneFlipX;
break;
case 3:
return RotateFlipType.Rotate180FlipNone;
break;
case 4:
return RotateFlipType.Rotate180FlipX;
break;
case 5:
return RotateFlipType.Rotate90FlipX;
break;
case 6:
return RotateFlipType.Rotate90FlipNone;
break;
case 7:
return RotateFlipType.Rotate270FlipX;
break;
case 8:
return RotateFlipType.Rotate270FlipNone;
break;
default:
return RotateFlipType.RotateNoneFlipNone;
}
}

Maxing out HTTP compression in IIS7

1:  In IIS7 manager, enable dynamic and static compriession.   (This adds <urlCompression doStaticCompression=”true” doDynamicCompression=”true” /> to applicationHost.config)

2: Open C:\Windows\System32\Inetsrv\Config\applicationHost.config and go to the httpCompression section. For both dynamicTypes and staticTypes: <mimetype=”*/*” enabled=”true”>

3:   Run appcmd in %systemroot%\system32\inetsrv\
appcmd set config /section:httpCompression /[name='gzip'].dynamicsCompressionLevel:10
appcmd set config /section:httpCompression /[name='gzip'].staticCompressionLevel:10

(Set the value to 7,8,or 9 for less CPU usage)

Note: compressing static files prevents them from displaying incrementally while the rest of the file downloads in the background. This may be useful for viewing partially loaded PDF’s, text files, images, etc. It may be appropriate to enable/disable compression per-directory in some cases.

More information on IIS7 HTTP compression.

Xcode All-In-One View

One thing I don’t like about the default Xcode layout is that all the views – code, debug, console, find, etc open in new windows by default.

If you’d rather not manage a bunch of Xcode windows all the time,  Xcode has a “hidden” All-One-One view which shows all your views in a single window and ads a page toggle which conveniently switched between code and debugging toolbars.  You can access under Preferences – General – Layout.  This took me a long time to figure out because the Layout dropdown is disabled when a project is open.  Maybe it’s my Visual Studio background, but I like the integrated view much better.

xcode_allinone

Switching from the Windows to the Mac version of Picasa

When I migrated my Picasa photo collection from Windows to Mac, I didn’t realize that the folder created when you save your changes changed from Originals to .picasaoriginals. To rename all the folders created with the Windows version, run this in terminal:

find . -name Originals -type d -execdir mv ‘{}’ \.picasaoriginals \;

Multithreaded queue process with C# & BackgroundWorker

And now for something completely different:

This weekend, my mail server was slammed by a spammer using a rogue account to create hundreds of thousands of spam emails that jammed my outbound mail queue. Mixed with the spam were valuable customer emails, so I had to sort through all the mail ASAP and delete anything that wasn’t legit.

First I tried a simple loop that loaded each file and deleted it if it contained a bad string. But that was taking a while, so I made my filter multithreaded.

First, I load a list of files to process:

string[] files = Directory.GetFiles(directory);
Console.WriteLine(files.Length + " files.");

(You can iterate through the files instead, but I wanted to see how many files there are.)

I instantiate the class with the BackgroundWorker:

DeleteProcess DeleteProcess = new DeleteProcess();

Now, I loop through the files, checking each for spam:

            foreach (string mFile in files)
            {
                if (CheckBlacklist(mFile))
                {
                    DeleteProcess.filesToDelete.Add(mFile);
                    if (!DeleteProcess.worker.IsBusy)
                        DeleteProcess.worker.RunWorkerAsync();
                }
            }

Instead of loading the whole file, I just read it until I determine that it is spam. Since 99% of messages were spam, this went pretty quickly:

 private static bool CheckBlacklist(string mFile)
        {
            using (StreamReader reader = new StreamReader(new FileStream(mFile, FileMode.Open, FileAccess.Read)))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    if (line.Contains("NIGERIA") || line.Contains("Message Delivery Delay"))
                        return true;
                }
            }
            return false;
        }

(By using FileAccess.Read, I speed things up a bit.)

Now for the delete thread. Here is how it’s wired up:

public List<string> filesToDelete = new List<string>();
 
        public BackgroundWorker worker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
 
        public DeleteProcess()
        {
            worker.DoWork += worker_DoWork;
            worker.ProgressChanged += worker_ProgressChanged;
            worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        }

The worker thread should get the first file name from the queue, delete the file, and then delete the filename list item:

 private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            while (filesToDelete.Count > 0)
            {
                worker.ReportProgress(0, filesToDelete[0].Replace(Program.directory, string.Empty));
                File.Delete(filesToDelete[0]);
                File.Delete(filesToDelete[0].Replace(@"Outgoing\Messages\", @"Outgoing\"));
                filesToDelete.RemoveAt(0);
            }
        }

When we’re done, we count the remaining files:

Console.WriteLine(Directory.GetFiles(Program.directory).Length + " files left.");

It’s possible to create a collection of BackgroundWorkers if you want to utilize multiple CPU’s, but the bottleneck in this case was the disk IO, so it wouldn’t help.

Sorting artists by first/last name in iTunes

picture-1Until today, I was very confused by the fact that iTunes sorted some of my artists by last name and some by first name.  Then I figured out why – when editing the mp3/aac meta tags, you can specify custom sort fields.  To change the sort field, select one or more songs, right click and Get Info.  Then select a sort artist or other sort fields in the Sorting tab.

AES interoperability between .Net and iPhone

One of my projects requires encrypting data on the iPhone and decrypting it using .Net. This is easy to do with the Common Crypto library in the iPhone SDK and the AesCryptoServiceProvider class in .Net, but the encryption parameters have to be the same for it to work.

I couldn’t figure it out, but the geniuses at StackOverflow did, so I am posting my results here. The zip file includes a basic iPhone app and a .Net console project with helpful classes to do the encryption/decryption and base64 conversion. I didn’t write most of the code – thanks to Blue Beetle for the .Net code and Greg Haygood for the Objective C.

Download zip.

OS X development resources?

Here’s an interesting collection of online Objective C/Cocoa tutorials. Can anyone suggest other online resources? I don’t have a good record of reading dead-tree instructional materials :-/

Update: here is a free ebook on OS X development.  I just pre-ordered this (the first edition has great reviews)
Programming in Objective-C 2.0 (2nd Edition) (Developer’s Library)

←Older